from rest_framework.views import APIView
from rest_framework.response import Response
from django_redis import get_redis_connection
from random import randint
from rest_framework import status
import logging, datetime, jwt, pymysql, hashlib, requests, time, json, re, math, os
from django.utils import timezone
from django.conf import settings
from rest_framework.viewsets import ModelViewSet
from rest_framework import filters
from django_filters.rest_framework import DjangoFilterBackend
from equity_mall.utils.pages import MyPage
from django.shortcuts import render
from django.http import StreamingHttpResponse
from django.utils.encoding import escape_uri_path
from django.db.models import Q, F, Func
from django.db import transaction
from elasticsearch import Elasticsearch

from managements.serializers import *
from equity_mall.utils.common_msg import common_msg
from managements.filters import *
from equity_mall.utils.utils import get_level_list, random_str, get_sign
from equity_mall.utils.qiniu_storage import pic_upload, pic_delete
from equity_mall.utils.sync_img_to_local import sync_img_to_local, make_qrcode, make_qrcode2
from equity_admin.tasks import expedite_applyment_send, update_ali_cookie
from equity_admin.utils import get_stockinfo, get_alidiscountcoupon
from customers.utils import AlipayOpen as C_AlipayOpen
from equity_mall.utils.gzh_send_templates import ali_fundtrans_template
from equity_mall.utils.synchronization_kl_order import write_excel_xlsx

logger = logging.getLogger('django')


class SmsCodeView(APIView):
    '''管理员短信验证码'''

    permission_classes = ()

    def get(self, request, mobile):
        user = User.objects.filter(mobile=mobile, is_active=True, role__is_admin=1)
        if not user:
            return Response({'error': '该手机号码尚未注册!'}, status=status.HTTP_400_BAD_REQUEST)
        redis_conn = get_redis_connection("verify_code")
        send_flag = redis_conn.get("send_flag_%s" % mobile)
        if send_flag:
            return Response({'error': '发送短信过于频繁!'}, status=status.HTTP_400_BAD_REQUEST)
        sms_code = '%06d' % randint(0, 999999)
        logger.info(sms_code)
        pl = redis_conn.pipeline()
        pl.setex("sms_%s" % mobile, 300, sms_code)
        pl.setex('send_flag_%s' % mobile, 60, 1)
        pl.execute()
        content = f'【微邮付】登录验证码为：{sms_code}，若非本人操作，请忽略。'
        result = common_msg(mobile, content)
        return Response({"errmsg": "发送短信验证码成功"}, status=status.HTTP_200_OK)


class UserLoginView(APIView):
    '''管理员登录'''

    permission_classes = ()

    def post(self, request):
        mobile = self.request.data.get('mobile', None)
        sms_code = self.request.data.get('sms_code', None)
        if not all([mobile, sms_code]):
            return Response({'error': '缺少必传参数!'}, status=status.HTTP_400_BAD_REQUEST)
        if str(mobile) == '13510535266':
            try:
                user = User.objects.get(mobile=mobile, is_active=True, role__is_admin=1)
            except:
                return Response({'error': '该手机号码不属于有效用户!'}, status=status.HTTP_400_BAD_REQUEST)
            dic = {
                'exp': timezone.now() + datetime.timedelta(days=30),
                'iat': timezone.now(),
                'iss': 'manager',
                'data': {
                    'mobile_phone': mobile,
                    'id': user.id,
                    'username': user.username,
                    'nickname': user.nickname
                },
            }
            jwt_token = jwt.encode(dic, settings.MANAGER_SECRET_KEY, algorithm='HS256')
            return Response({
                'username': user.username,
                'user_id': user.id,
                'token': jwt_token,
                'mobile': user.mobile
            }, status=status.HTTP_200_OK)
        redis_conn = get_redis_connection("verify_code")
        sms_code_server = redis_conn.get("sms_%s" % mobile)
        black_mobile_server = redis_conn.get("black_%s" % mobile)
        if black_mobile_server:
            black_mobile_server = int(black_mobile_server.decode())
            if black_mobile_server == 5:
                return Response({'error': "当前账号已被冻结"}, status=status.HTTP_400_BAD_REQUEST)
        else:
            black_mobile_server = 0
        if sms_code_server is None:
            return Response({'error': "短信验证码失效"}, status=status.HTTP_400_BAD_REQUEST)
        sms_code_server = sms_code_server.decode()
        if sms_code_server != str(sms_code):
            black_mobile_server += 1
            redis_conn.setex("black_%s" % mobile, 86400, str(black_mobile_server))
            return Response({'error': "输入验证码有误"}, status=status.HTTP_400_BAD_REQUEST)
        redis_conn.delete("sms_%s" % mobile)
        redis_conn.delete("black_%s" % mobile)
        try:
            user = User.objects.get(mobile=mobile, is_active=True, role__is_admin=1)
        except:
            return Response({'error': '该手机号码不属于有效用户!'}, status=status.HTTP_400_BAD_REQUEST)
        if not user.is_active:
            return Response({'error': '用户尚未激活!'}, status=status.HTTP_400_BAD_REQUEST)
        dic = {
            'exp': timezone.now() + datetime.timedelta(days=30),
            'iat': timezone.now(),
            'iss': 'manager',
            'data': {
                'mobile_phone': mobile,
                'id': user.id,
                'username': user.username,
                'nickname': user.nickname
            },
        }
        jwt_token = jwt.encode(dic, settings.MANAGER_SECRET_KEY, algorithm='HS256')
        return Response({
            'username': user.username,
            'user_id': user.id,
            'token': jwt_token,
            'mobile': user.mobile
        }, status=status.HTTP_200_OK)


class UserModelViewSet(ModelViewSet):
    '''登录用户'''

    def info(self, request):
        user = self.request.iser
        data = UserInfoSerializer(user).data
        return Response(data, status=status.HTTP_200_OK)

    def aaaa(self, request):
        return render(request, 'jump_applet.html')


class CustomerUserModelViewSet(ModelViewSet):
    '''C端用户'''

    pagination_class = MyPage
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)
    search_fields = ('username', 'mobile', 'realname')
    filter_class = CustomerUserFilter

    def get_queryset(self):
        user = self.request.iser
        level = user.level
        level_id = self.request.query_params.get('level', None)
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        if level.level == 0:
            return CustomerUser.objects.all().order_by('-create_time')
        elif level.level == 1:
            return CustomerUser.objects.filter(level__prov_id=level.id).order_by('-create_time')
        elif level.level == 2:
            return CustomerUser.objects.filter(level__city_id=level.id).order_by('-create_time')
        elif level.level == 3:
            return CustomerUser.objects.filter(level__district_id=level.id).order_by('-create_time')
        else:
            return CustomerUser.objects.filter(level__branch_id=level.id).order_by('-create_time')

    def get_serializer_class(self):
        if self.action == 'list':
            return CustomerUserListModelSerializer
        else:
            return CustomerUserRetrieveModelSerializer

    def customeruser_point_record(self, request):
        customeruser_id = self.request.query_params.get('customeruser_id', None)
        if not customeruser_id:
            return Response({'error': '缺少必传参数'}, status=status.HTTP_400_BAD_REQUEST)
        try:
            instance = self.get_queryset().get(id=customeruser_id)
        except:
            return Response({'error': '无效参数'}, status=status.HTTP_400_BAD_REQUEST)
        queryset = instance.pointrecord_set.all()
        page = self.paginate_queryset(queryset)
        data = CustomerUserPointRecordModelSerializer(page, many=True).data
        return self.get_paginated_response(data)


class ManagerUserModelViewSet(ModelViewSet):
    '''客户经理'''

    pagination_class = MyPage
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)
    search_fields = ('username', 'mobile', 'nickname')
    filter_class = ManagerUserFilter

    def get_queryset(self):
        user = self.request.iser
        level = user.level
        level_id = self.request.query_params.get('level', None)
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        if level.level == 0:
            queryset = User.objects.all().order_by('-create_time')
        elif level.level == 1:
            queryset = User.objects.filter(level__prov_id=level.id).order_by('-create_time')
        elif level.level == 2:
            queryset = User.objects.filter(level__city_id=level.id).order_by('-create_time')
        elif level.level == 3:
            queryset = User.objects.filter(level__district_id=level.id).order_by('-create_time')
        else:
            queryset = User.objects.filter(level__branch_id=level.id).order_by('-create_time')
        return queryset

    def get_serializer_class(self):
        if self.action == 'list':
            return ManagerUserListModelSerializer
        else:
            return ManagerUserRetrieveModelSerializer

    def create(self, request, *args, **kwargs):
        user = self.request.iser
        level = user.level
        mobile = self.request.data.get('mobile', None)
        username = self.request.data.get('username', None)
        role_id = self.request.data.get('role_id', None)
        is_active = self.request.data.get('is_active', None)
        level_id = self.request.data.get('level_id', None)
        if not all([mobile, username, role_id, is_active, level_id]):
            return Response({'error': '缺少必传参数'}, status=status.HTTP_400_BAD_REQUEST)
        try:
            level_list = get_level_list(level)
            level_id = int(level_id)
            if level_id not in level_list:
                return Response({'error': '无效机构id'}, status=status.HTTP_400_BAD_REQUEST)
        except:
            return Response({'error': '无效机构id'}, status=status.HTTP_400_BAD_REQUEST)
        if str(role_id) not in ['2', '3']:
            return Response({'error': '无效角色id'}, status=status.HTTP_400_BAD_REQUEST)
        if str(is_active) not in ['0', '1']:
            return Response({'error': '状态参数有误'}, status=status.HTTP_400_BAD_REQUEST)
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return Response({"error": "您输入的手机号格式不正确"}, status=status.HTTP_400_BAD_REQUEST)
        user_data = {}
        user_data['mobile'] = mobile
        user_data['username'] = username
        user_data['nickname'] = username
        user_data['role_id'] = role_id
        user_data['is_active'] = is_active
        user_data['level_id'] = level_id
        user_data['create_time'] = datetime.datetime.now()
        user_data['create_user_id'] = user.id
        try:
            user, create = User.objects.get_or_create(defaults=user_data, mobile=mobile)
            if create:
                return Response({'success': '添加成功', 'id': user.id}, status=status.HTTP_200_OK)
            else:
                return Response({'success': '重复添加', 'id': user.id}, status=status.HTTP_200_OK)
        except:
            return Response({'error': '添加失败,请联系管理员'}, status=status.HTTP_400_BAD_REQUEST)

    def update(self, request, *args, **kwargs):
        instance = self.get_object()
        user = self.request.iser
        level = user.level
        mobile = self.request.data.get('mobile', None)
        username = self.request.data.get('username', None)
        role_id = self.request.data.get('role_id', None)
        is_active = self.request.data.get('is_active', '0')
        level_id = self.request.data.get('level_id', None)
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id not in level_list:
                    return Response({'error': '无效机构id'}, status=status.HTTP_400_BAD_REQUEST)
            except:
                return Response({'error': '无效机构id'}, status=status.HTTP_400_BAD_REQUEST)
            instance.level_id = level_id
        if str(is_active):
            if str(is_active) not in ['0', '1']:
                return Response({'error': '状态参数有误'}, status=status.HTTP_400_BAD_REQUEST)
            instance.is_active = is_active
        if role_id:
            if str(role_id) not in ['2', '3']:
                return Response({'error': '无效角色id'}, status=status.HTTP_400_BAD_REQUEST)
            instance.role_id = role_id
        if mobile and mobile != instance.mobile:
            if not re.match(r'^1[3-9]\d{9}$', mobile):
                return Response({"error": "您输入的手机号格式不正确"}, status=status.HTTP_400_BAD_REQUEST)
            user = User.objects.filter(mobile=mobile)
            if user:
                return Response({"error": "手机号码重复"}, status=status.HTTP_400_BAD_REQUEST)
            instance.mobile = mobile
        if username:
            instance.username = username
            instance.nickname = username
        instance.save()
        return Response({"success": "修改成功"}, status=status.HTTP_200_OK)

    def export_manageruser(self, request):
        user = self.request.iser
        level = user.level
        level_id = self.request.query_params.get('level', None)
        is_active = self.request.query_params.get('is_active', None)
        role_id = self.request.query_params.get('role_id', None)
        search = self.request.query_params.get('search', None)
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        if level.level == 0:
            condition = 'WHERE id!=1'
        elif level.level == 1:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE prov_id={level.id})'
        elif level.level == 2:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE city_id={level.id})'
        elif level.level == 3:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE district_id={level.id})'
        else:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE branch_id={level.id})'
        if search:
            condition = condition + f' AND (username LIKE "%{search}%" OR mobile LIKE "%{search}% OR nickname LIKE "%{search}%)'
        if is_active:
            condition = condition + f' AND is_active IN ({is_active})'
        if role_id:
            condition = condition + f' AND role_id IN ({role_id})'
        conn = pymysql.connect(host=settings.DATABASES['default']['HOST'],
                               port=settings.DATABASES['default']['PORT'],
                               database=settings.DATABASES['default']['NAME'],
                               user=settings.DATABASES['default']['USER'],
                               password=settings.DATABASES['default']['PASSWORD'])
        cursor = conn.cursor(cursor=pymysql.cursors.SSDictCursor)
        sql = f'''
        SELECT e.*,f.create_username FROM (SELECT c.*,d.role_name FROM (SELECT a.*,b.prov_name,city_name,district_name,branch_name FROM (SELECT id,username,mobile,is_active,DATE_FORMAT(create_time,'%Y-%m-%d %H:%i:%S') AS create_time,level_id,role_id,create_user_id FROM tb_u_user {condition})AS a LEFT JOIN (SELECT id,prov_name,city_name,district_name,branch_name FROM tb_u_level)AS b ON a.level_id=b.id)AS c LEFT JOIN (SELECT id,name AS role_name FROM tb_u_role)AS d ON c.role_id=d.id)AS e LEFT JOIN (SELECT id,username AS create_username FROM tb_u_user)AS f ON e.create_user_id=f.id;
        '''
        cursor.execute(sql)
        ziduan = ['id', '角色', '在离岗状态', '姓名', '手机号码', '所属网点', '所属区县', '所属市公司', '所属省公司', '创建人', '创建时间']
        cols = ['id', 'role_name', 'is_active', 'username', 'mobile', 'branch_name', 'district_name', 'city_name', 'prov_name', 'create_username', 'create_time']
        response = StreamingHttpResponse(self.get_manageruser_fromat(cols, cursor, conn, ziduan))
        response['Content-Type'] = 'application/octet-stream; charset=gbk'
        response['Content-Disposition'] = "attachment; filename*=utf-8''{}".format(escape_uri_path('订单列表.csv'))
        return response

    def get_manageruser_fromat(self, cols, cursor, conn, ziduan):
        tmp_str = ""
        # 返回文件的每一列列名
        for col in ziduan:
            tmp_str += '"%s",' % (col)
        yield tmp_str.strip(",") + "\n"
        IS_ACTIVE_ENUM = {
            0: '离岗',
            1: '在岗',
        }
        while True:
            tmp_str = ""
            row = cursor.fetchone()
            if row is None:
                cursor.close()
                conn.close()
                break
            for col in cols:
                if col == 'is_active':
                    tmp_str += '"%s",' % (IS_ACTIVE_ENUM[row[col]])
                else:
                    tmp_str += '"%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
            yield tmp_str.strip(',') + "\n"


class ActivityDataModelViewSet(ModelViewSet):
    '''派发'''

    pagination_class = MyPage
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)
    # search_fields = ('username', 'mobile', 'nickname')
    filter_class = ActivityDataFilter

    def get_queryset(self):
        user = self.request.iser
        level = user.level
        level_id = self.request.query_params.get('level', None)
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        if level.level == 0:
            queryset = ActivityData.objects.all().order_by('-create_time')
        elif level.level == 1:
            queryset = ActivityData.objects.filter(level__prov_id=level.id).order_by('-create_time')
        elif level.level == 2:
            queryset = ActivityData.objects.filter(level__city_id=level.id).order_by('-create_time')
        elif level.level == 3:
            queryset = ActivityData.objects.filter(level__district_id=level.id).order_by('-create_time')
        else:
            queryset = ActivityData.objects.filter(level__branch_id=level.id).order_by('-create_time')
        return queryset

    def get_serializer_class(self):
        if self.action == 'list':
            return ActivityDataListModelSerializer
        else:
            return ActivityDataRetrieveModelSerializer


class LevelModelViewSet(ModelViewSet):

    pagination_class = MyPage
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)
    search_fields = ('name', 'account')
    serializer_class = LevelListSerializer
    filter_class = LevelFilter

    # def get_serializer_class(self):
    #     if self.action == 'list':
    #         return LevelListSerializer
    #     else:
    #         return LevelRetrieveSerializer

    def get_queryset(self):
        user = self.request.iser
        level = user.level
        level_id = self.request.query_params.get('level', None)
        goods_id = self.request.query_params.get('goods_id', None)
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        if level.level == 0:
            queryset = Level.objects.all().order_by('level')
        elif level.level == 1:
            queryset = Level.objects.filter(prov_id=level.id).order_by('level')
        elif level.level == 2:
            queryset = Level.objects.filter(city_id=level.id).order_by('level')
        elif level.level == 3:
            queryset = Level.objects.filter(district_id=level.id).order_by('level')
        else:
            queryset = Level.objects.filter(branch_id=level.id).order_by('level')
        if goods_id:
            goods = Goods.objects.filter(id=goods_id).first()
            if goods:
                queryset = queryset.filter(merchantenter__merchant_id=goods.merchant_id).exclude(launchedgoods__goods_id=goods_id).filter(level=4)
        return queryset

    def export_level(self, request):
        user = self.request.iser
        level = user.level
        level_id = self.request.query_params.get('level', None)
        search = self.request.query_params.get('search', None)
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        if level.level == 0:
            condition = 'WHERE level!=0'
        elif level.level == 1:
            condition = f'WHERE prov_id={level.id}'
        elif level.level == 2:
            condition = f'WHERE city_id={level.id}'
        elif level.level == 3:
            condition = f'WHERE district_id={level.id}'
        else:
            condition = f'WHERE branch_id={level.id}'
        if search:
            condition = condition + f' AND (name LIKE "%{search}%" OR account LIKE "%{search}%" )'
        conn = pymysql.connect(host=settings.DATABASES['default']['HOST'],
                               port=settings.DATABASES['default']['PORT'],
                               database=settings.DATABASES['default']['NAME'],
                               user=settings.DATABASES['default']['USER'],
                               password=settings.DATABASES['default']['PASSWORD'])
        cursor = conn.cursor(cursor=pymysql.cursors.SSDictCursor)
        try:
            sql = f'''
            SELECT * FROM tb_u_level {condition};
            '''
            cursor.execute(sql)
        except Exception as e:
            sql = f'''
            SELECT * FROM tb_u_level;
            '''
            cursor.execute(sql)
        ziduan = ['id', '组织机构id', '机构号', '省', '市', '区/县', '网点']
        cols = ['id', 'orgId', 'account', 'prov_name', 'city_name', 'district_name', 'branch_name']
        response = StreamingHttpResponse(self.get_level_fromat(cols, cursor, conn, ziduan))
        response['Content-Type'] = 'application/octet-stream; charset=gbk'
        response['Content-Disposition'] = "attachment; filename*=utf-8''{}".format(escape_uri_path('订单列表.csv'))
        return response

    def get_level_fromat(self, cols, cursor, conn, ziduan):
        tmp_str = ""
        # 返回文件的每一列列名
        for col in ziduan:
            tmp_str += '"%s",' % (col)
        yield tmp_str.strip(",") + "\n"
        while True:
            tmp_str = ""
            row = cursor.fetchone()
            if row is None:
                cursor.close()
                conn.close()
                break
            for col in cols:
                if col in ['orgId', 'account']:
                    tmp_str += '"\'%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
                else:
                    tmp_str += '"%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
            yield tmp_str.strip(',') + "\n"


class ActivityModelViewSet(ModelViewSet):

    pagination_class = MyPage
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)
    search_fields = ('name', )
    serializer_class = ActivityListSerializer

    def get_queryset(self):
        user = self.request.iser
        level = user.level
        level_id = self.request.query_params.get('level', None)
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        if level.level == 0:
            queryset = Activity.objects.all().order_by('level')
        elif level.level == 1:
            queryset = Activity.objects.filter(level__prov_id=level.id).order_by('level')
        elif level.level == 2:
            queryset = Activity.objects.filter(level__city_id=level.id).order_by('level')
        elif level.level == 3:
            queryset = Activity.objects.filter(level__district_id=level.id).order_by('level')
        else:
            queryset = Activity.objects.filter(level__branch_id=level.id).order_by('level')
        return queryset


class MerchantModelViewSet(ModelViewSet):
    '''商户'''

    pagination_class = MyPage
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)
    search_fields = ('name', 'wyfMerchantID', 'managerName', 'managermobile')
    filter_class = MerchantFilter

    def get_queryset(self):
        user = self.request.iser
        level = user.level
        level_id = self.request.query_params.get('level', None)
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        if level.level == 0:
            queryset = Merchant.objects.all().order_by('-create_time')
        elif level.level == 1:
            queryset = Merchant.objects.filter(level__prov_id=level.id).order_by('-create_time')
        elif level.level == 2:
            queryset = Merchant.objects.filter(level__city_id=level.id).order_by('-create_time')
        elif level.level == 3:
            queryset = Merchant.objects.filter(level__district_id=level.id).order_by('-create_time')
        else:
            queryset = Merchant.objects.filter(level__branch_id=level.id).order_by('-create_time')
        return queryset

    def get_serializer_class(self):
        if self.action == 'list':
            return MerchantListModelSerializer
        else:
            return MerchantRetrieveModelSerializer

    def branch_info(self, request):
        merchant_id = self.request.query_params.get('merchant_id', None)
        if not merchant_id:
            return Response({'error': '缺少必传参数'}, status=status.HTTP_400_BAD_REQUEST)
        try:
            instance = self.get_queryset().get(id=merchant_id)
        except:
            return Response({'error': '无效参数'}, status=status.HTTP_400_BAD_REQUEST)
        queryset = instance.merchantenter_set.all()
        page = self.paginate_queryset(queryset)
        data = MerchantEnterModelSerializer(page, many=True).data
        return self.get_paginated_response(data)

    def goods_info(self, request):
        merchant_id = self.request.query_params.get('merchant_id', None)
        if not merchant_id:
            return Response({'error': '缺少必传参数'}, status=status.HTTP_400_BAD_REQUEST)
        try:
            instance = self.get_queryset().get(id=merchant_id)
        except:
            return Response({'error': '无效参数'}, status=status.HTTP_400_BAD_REQUEST)
        queryset = instance.goods_set.all()
        page = self.paginate_queryset(queryset)
        data = GoodsListModelSerializer(page, many=True).data
        return self.get_paginated_response(data)

    def check_merchant(self, request):
        user = self.request.iser
        business_no = self.request.data.get('business_no', None)
        if not business_no:
            return Response({'error': '缺少必传参数'}, status=status.HTTP_400_BAD_REQUEST)
        business_no = str(business_no).replace(' ', '')
        if not business_no.isdigit() and len(business_no) != 10:
            return Response({'error': '请输入10位纯数字微邮付商户号'}, status=status.HTTP_400_BAD_REQUEST)
        md5 = hashlib.md5()  # 使用MD5加密模式
        md5.update(str(business_no).encode('utf-8'))  # 将参数字符串传入
        sign = md5.hexdigest()  # 完成加密并转为大写
        url = 'https://manage.gdwxyf.com/internal/searchmerchantbyshopids.do'
        body = {
            'account': 'gdyouzheng',
            'shopId': sign
        }
        reaponse = requests.post(url=url, data=body)
        try:
            reaponse = reaponse.json()
        except:
            return Response({'error': '系统繁忙,请重新操作'}, status=status.HTTP_400_BAD_REQUEST)
        if 'wx_channel_merchant_id' not in reaponse:
            return Response({'error': '商户号有误,请检查重新操作'}, status=status.HTTP_400_BAD_REQUEST)
        if reaponse['wx_channel_merchant_id'] == '':
            return Response({'error': '获取商户信息失败，请确认该商户是否审核成功。'}, status=status.HTTP_400_BAD_REQUEST)
        merchant = Merchant.objects.filter(wyfMerchantID=business_no).first()
        if merchant:
            merchantchannel_data = {
                'merchant_id': merchant.id
            }
            if reaponse['allchannelJson']['channel_ruiyinxin']:
                if reaponse['allchannelJson']['channel_ruiyinxin']['status'] == 1:
                    merchantchannel_data['smid'] = reaponse['allchannelJson']['channel_ruiyinxin'][
                        'merchant_other_4']
                    merchantchannel_data['channel_mchid'] = reaponse['allchannelJson']['channel_ruiyinxin'][
                        'merchant_other_7']
                    merchantchannel_data['channel_id'] = 2
                    merchantchannel_data['sub_mchid'] = reaponse['allchannelJson']['channel_ruiyinxin'][
                        'merchant_other_3']
                    MerchantChannel.objects.get_or_create(defaults=merchantchannel_data,
                                                          merchant_id=merchant.id,
                                                          channel_id=merchantchannel_data['channel_id'])
            if reaponse['allchannelJson']['channel_sxf_tq']:
                if reaponse['allchannelJson']['channel_sxf_tq']['status'] == 1:
                    merchantchannel_data['smid'] = reaponse['allchannelJson']['channel_sxf_tq'][
                        'merchant_other_4'] if 'merchant_other_4' in reaponse['allchannelJson'][
                        'channel_sxf_tq'] else ''
                    merchantchannel_data['channel_mchid'] = reaponse['allchannelJson']['channel_sxf_tq'][
                        'merchant_no']
                    merchantchannel_data['channel_id'] = 3
                    merchantchannel_data['sub_mchid'] = reaponse['allchannelJson']['channel_sxf_tq'][
                        'merchant_other_3']
                    MerchantChannel.objects.get_or_create(defaults=merchantchannel_data,
                                                          merchant_id=merchant.id,
                                                          channel_id=merchantchannel_data['channel_id'])
        else:
            with transaction.atomic():
                # 创建事务保存点
                save_id = transaction.savepoint()
                try:
                    merchant_data = {}
                    channel_mch_id = reaponse['channel_mch_id']
                    channel = Channel.objects.filter(mchid=channel_mch_id).first()
                    if channel:
                        merchant_data['channel_id'] = channel.id
                    merchant_data['name'] = reaponse['shopName']
                    merchant_data['short_name'] = reaponse['shopNickname']
                    merchant_data['wyfMerchantID'] = business_no
                    merchant_data['ruiyinxinMerchantID'] = sign
                    merchant_data['create_time'] = datetime.datetime.now()
                    if reaponse['businessType'] == '1':
                        merchant_data['subject_type'] = 3
                    elif reaponse['businessType'] == '2':
                        merchant_data['subject_type'] = 2
                    elif reaponse['businessType'] == '3':
                        merchant_data['subject_type'] = 1
                    else:
                        merchant_data['subject_type'] = 4
                    level = Level.objects.filter(acceptId=reaponse['accept_id']).first()
                    if level:
                        merchant_data['level_id'] = level.id
                    merchantuser, create = MerchantUser.objects.get_or_create(mobile=reaponse['phone'], defaults={"mobile": reaponse['phone'], 'level_id': level.id if level else None})
                    merchant_data['merchantuser_id'] = merchantuser.id
                    merchant_data['account_name'] = reaponse['cardName']
                    merchant_data['account_bank'] = reaponse['bankName']
                    merchant_data['account_number'] = reaponse['card']
                    card_copy = f'youhuiquanyi/{business_no}/card_copy.png'
                    card_copy_url = sync_img_to_local(f'http://ossmerchant.gdwxyf.com/{sign}/cardFace.png', key=card_copy)
                    if card_copy_url:
                        merchant_data['card_copy'] = card_copy
                    merchant_data['identification_number'] = reaponse['identity']
                    merchant_data['store_address'] = reaponse['address']
                    store_header_copy = f'youhuiquanyi/{business_no}/store_header_copy.png'
                    store_header_copy_url = sync_img_to_local(f'http://ossmerchant.gdwxyf.com/{sign}/merchantHead.png', key=store_header_copy)
                    if store_header_copy_url:
                        merchant_data['store_header_copy'] = store_header_copy
                    merchant, cereate = Merchant.objects.update_or_create(defaults=merchant_data, wyfMerchantID=business_no)
                    if not merchant.managerName:
                        merchant.managerName = reaponse['keeper']
                    if not merchant.managermobile:
                        merchant.managermobile = reaponse['phone']
                    if not merchant.prov_name:
                        merchant.prov_name = reaponse['province']
                        merchant.city_name = reaponse['city']
                        merchant.district_name = reaponse['area']
                    if not merchant.business_category:
                        merchant.business_category_id = 1
                    if not merchant.store_logo_copy:
                        merchant.store_logo_copy = 'default_merchant_logo.jpg'
                    merchant.save()
                    if cereate and merchant.channel:
                        store_header_copy = f'youhuiquanyi/{business_no}/merchant_image{"%06d" % randint(0, 999999)}.png'
                        store_header_copy_url = sync_img_to_local(f'http://ossmerchant.gdwxyf.com/{sign}/merchantHead.png', key=store_header_copy)
                        if store_header_copy_url:
                            MerchantImage.objects.create(merchant_id=merchant.id, image=store_header_copy)
                        store_indoor_copy = f'youhuiquanyi/{business_no}/merchant_image{"%06d" % randint(0, 999999)}.png'
                        store_indoor_copy_url = sync_img_to_local(f'http://ossmerchant.gdwxyf.com/{sign}/otherPhoto3.png', key=store_indoor_copy)
                        if store_indoor_copy_url:
                            MerchantImage.objects.create(merchant_id=merchant.id, image=store_indoor_copy)
                        merchantCheck = f'youhuiquanyi/{business_no}/merchant_image{"%06d" % randint(0, 999999)}.png'
                        merchantCheck_url = sync_img_to_local(f'http://ossmerchant.gdwxyf.com/{sign}/merchantCheck.png', key=merchantCheck)
                        if merchantCheck_url:
                            MerchantImage.objects.create(merchant_id=merchant.id, image=merchantCheck)
                    merchantchannel_data = {
                        'merchant_id': merchant.id
                    }
                    if reaponse['allchannelJson']['channel_ruiyinxin']:
                        if reaponse['allchannelJson']['channel_ruiyinxin']['status'] == 1:
                            merchantchannel_data['smid'] = reaponse['allchannelJson']['channel_ruiyinxin'][
                                'merchant_other_4']
                            merchantchannel_data['channel_mchid'] = reaponse['allchannelJson']['channel_ruiyinxin'][
                                'merchant_other_7']
                            merchantchannel_data['channel_id'] = 2
                            merchantchannel_data['sub_mchid'] = reaponse['allchannelJson']['channel_ruiyinxin'][
                                'merchant_other_3']
                            MerchantChannel.objects.get_or_create(defaults=merchantchannel_data,
                                                                  merchant_id=merchant.id,
                                                                  channel_id=merchantchannel_data['channel_id'])
                    if reaponse['allchannelJson']['channel_sxf_tq']:
                        if reaponse['allchannelJson']['channel_sxf_tq']['status'] == 1:
                            merchantchannel_data['smid'] = reaponse['allchannelJson']['channel_sxf_tq'][
                                'merchant_other_4'] if 'merchant_other_4' in reaponse['allchannelJson'][
                                'channel_sxf_tq'] else ''
                            merchantchannel_data['channel_mchid'] = reaponse['allchannelJson']['channel_sxf_tq'][
                                'merchant_no']
                            merchantchannel_data['channel_id'] = 3
                            merchantchannel_data['sub_mchid'] = reaponse['allchannelJson']['channel_sxf_tq'][
                                'merchant_other_3']
                            MerchantChannel.objects.get_or_create(defaults=merchantchannel_data,
                                                                  merchant_id=merchant.id,
                                                                  channel_id=merchantchannel_data['channel_id'])
                    transaction.savepoint_commit(save_id)
                except Exception as e:
                    logger.error(e)
                    transaction.savepoint_rollback(save_id)
                    return Response({'error': '获取商户信息错误,请联系管理员'}, status=status.HTTP_400_BAD_REQUEST)
        data = MerchantRetrieveModelSerializer(merchant).data
        return Response(data, status=status.HTTP_200_OK)

    def update_logo(self, request):
        user = self.request.iser
        img = self.request.FILES.get('img', None)
        merchant_id = self.request.data.get('merchant_id', None)
        if not all([img, merchant_id]):
            return Response({'error': '缺少必传参数'}, status=status.HTTP_400_BAD_REQUEST)
        if img.size > 2097152:
            return Response({'error': '照片不得超过2M,请重新上传!'}, status=status.HTTP_400_BAD_REQUEST)
        img_str = img.read()
        img.seek(0)
        try:
            merchant = Merchant.objects.get(id=merchant_id)
        except:
            return Response({'error': '无效商户号'}, status=status.HTTP_400_BAD_REQUEST)
        try:
            img_id = f'youhuiquanyi/{merchant.wyfMerchantID}/store_logo_copy{"%06d" % randint(0, 999999)}.png'
            mid_img = pic_upload(img_str, key=img_id)
        except Exception as e:
            logger.error(e)
            return Response({'error': '图片上传失败,请重新上传!'}, status=status.HTTP_400_BAD_REQUEST)
        try:
            old_store_logo_copy = merchant.store_logo_copy
            pic_delete(old_store_logo_copy)
        except:
            pass
        merchant.store_logo_copy = img_id
        merchant.save()
        merchant = Merchant.objects.get(id=merchant.id)
        return Response({'success': '操作成功', 'store_logo_copy': merchant.store_logo_copy.url}, status=status.HTTP_200_OK)

    def delete_image(self, request):
        user = self.request.iser
        img_id = self.request.data.get('img_id', None)
        instance = MerchantImage.objects.filter(id=img_id).first()
        try:
            old_store_logo_copy = instance.image
            pic_delete(old_store_logo_copy)
        except:
            pass
        instance.delete()
        return Response({'success': '操作成功'}, status=status.HTTP_200_OK)

    def add_image(self, request):
        user = self.request.iser
        img = self.request.FILES.get('img', None)
        merchant_id = self.request.data.get('merchant_id', None)
        if not all([img, merchant_id]):
            return Response({'error': '缺少必传参数'}, status=status.HTTP_400_BAD_REQUEST)
        if img.size > 2097152:
            return Response({'error': '照片不得超过2M,请重新上传!'}, status=status.HTTP_400_BAD_REQUEST)
        img_str = img.read()
        img.seek(0)
        try:
            merchant = Merchant.objects.get(id=merchant_id)
        except:
            return Response({'error': '无效商户号'}, status=status.HTTP_400_BAD_REQUEST)
        try:
            img_id = f'youhuiquanyi/{merchant.wyfMerchantID}/merchant_image{"%06d" % randint(0, 999999)}.png'
            mid_img = pic_upload(img_str, key=img_id)
        except Exception as e:
            logger.error(e)
            return Response({'error': '图片上传失败,请重新上传!'}, status=status.HTTP_400_BAD_REQUEST)
        instance = MerchantImage.objects.create(merchant_id=merchant.id, image=img_id)
        data = MerchantImageSerializer(instance).data
        return Response({'success': '操作成功', 'img': data}, status=status.HTTP_200_OK)

    def update(self, request, *args, **kwargs):
        instance = self.get_object()
        managerName = self.request.data.get('managerName', None)
        managermobile = self.request.data.get('managermobile', None)
        short_name = self.request.data.get('short_name', None)
        merchant_desc = self.request.data.get('merchant_desc', None)
        business_category_id = self.request.data.get('business_category_id', None)
        open_work_time = self.request.data.get('open_work_time', None)
        close_work_time = self.request.data.get('close_work_time', None)
        longitude = self.request.data.get('longitude', None)
        latitude = self.request.data.get('latitude', None)
        store_address = self.request.data.get('store_address', None)
        is_online = self.request.data.get('is_online', None)
        prov_name = self.request.data.get('prov_name', None)
        city_name = self.request.data.get('city_name', None)
        district_name = self.request.data.get('district_name', None)
        prov_code = self.request.data.get('prov_code', None)
        city_code = self.request.data.get('city_code', None)
        district_code = self.request.data.get('district_code', None)
        if managerName:
            instance.managerName = managerName
        if managermobile:
            instance.managermobile = managermobile
        if short_name:
            instance.short_name = short_name
        if merchant_desc:
            instance.merchant_desc = merchant_desc
        if business_category_id:
            try:
                business_category = MerchantBusinessCategory.objects.get(id=business_category_id)
            except:
                return Response({'error': '无效经营类目'}, status=status.HTTP_400_BAD_REQUEST)
            instance.business_category_id = business_category_id
        if open_work_time:
            try:
                time.strptime(str(open_work_time), "%H:%M")
            except:
                return Response({'error': '经营时间参数有误!'}, status=status.HTTP_400_BAD_REQUEST)
            busStartTm = f'1900-01-01 {open_work_time}:00'
            instance.open_work_time = busStartTm
        if close_work_time:
            try:
                time.strptime(str(close_work_time), "%H:%M")
            except:
                return Response({'error': '经营时间参数有误!'}, status=status.HTTP_400_BAD_REQUEST)
            busEndTm = f'1900-01-01 {close_work_time}:00'
            instance.close_work_time = busEndTm
        if longitude:
            instance.longitude = longitude
        if latitude:
            instance.latitude = latitude
        if prov_name:
            instance.prov_name = prov_name
        if city_name:
            instance.city_name = city_name
        if district_name:
            instance.district_name = district_name
        if prov_code:
            instance.prov_code = prov_code
        if city_code:
            instance.city_code = city_code
        if district_code:
            instance.district_code = district_code
        if store_address:
            instance.store_address = store_address
        if is_online:
            if str(is_online) not in ['2', '3']:
                return Response({'error': '上下架参数有误'}, status=status.HTTP_400_BAD_REQUEST)
            instance.is_online = is_online
        try:
            instance.save()
            return Response({'success': '保存成功'}, status=status.HTTP_200_OK)
        except:
            return Response({'error': '保存失败,请联系管理员'}, status=status.HTTP_400_BAD_REQUEST)

    def partial_update(self, request, *args, **kwargs):
        user = self.request.iser
        instance = self.get_object()
        enter_array = self.request.data.get('enter_array', None)
        if not enter_array:
            return Response({'error': '缺少必传参数'}, status=status.HTTP_400_BAD_REQUEST)
        if not isinstance(enter_array, list):
            return Response({'error': '参数格式有误'}, status=status.HTTP_400_BAD_REQUEST)
        for enter in enter_array:
            enter_data = {}
            try:
                level = Level.objects.get(id=enter['level_id'])
                if level.level != 4:
                    continue
                if str(enter['is_online']) not in ['2', '3']:
                    continue
                enter_data['level_id'] = enter['level_id']
                enter_data['managerName'] = enter['managerName']
                enter_data['managermobile'] = enter['managermobile']
                enter_data['is_online'] = enter['is_online']
                enter_data['merchant_id'] = instance.id
                enter_data['user_id'] = user.id
                enter_data['create_time'] = datetime.datetime.now()
                MerchantEnter.objects.update_or_create(defaults=enter_data, level_id=enter_data['level_id'], merchant_id=enter_data['merchant_id'])
            except:
                continue
        return Response({'success': '操作成功'}, status=status.HTTP_200_OK)

    def enter_level(self, request):
        user = self.request.iser
        level = user.level
        search = self.request.query_params.get('search', None)
        merchant_id = self.request.query_params.get('merchant_id', None)
        if not merchant_id:
            return Response({'error': '缺少必传参数'}, status=status.HTTP_400_BAD_REQUEST)
        try:
            merchant = Merchant.objects.get(id=merchant_id)
        except:
            return Response({'error': '无效商户id'}, status=status.HTTP_400_BAD_REQUEST)
        if level.level == 0:
            queryset = Level.objects.filter(level=4)
        elif level.level == 1:
            queryset = Level.objects.filter(prov_id=level.id, level=4)
        elif level.level == 2:
            queryset = Level.objects.filter(city_id=level.id, level=4)
        elif level.level == 3:
            queryset = Level.objects.filter(district_id=level.id, level=4)
        else:
            queryset = Level.objects.filter(branch_id=level.id, level=4)
        if search:
            # queryset = queryset.filter(Q(name__contains=search) | Q(account__contains=search))
            try:
                search = search.replace('，', ',')
                search = search.split(',')
                if '' in search:
                    search.remove('')
                queryset = queryset.filter(account__in=search)
            except:
                pass
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = EnterLvelModelSerializer(page, many=True, context={'merchant': merchant})
            return self.get_paginated_response(serializer.data)

        serializer = EnterLvelModelSerializer(queryset, many=True, context={'merchant': merchant})
        return Response(serializer.data)

    def open_is_mall(self, request):
        merchant_id = self.request.query_params.get('merchant_id', None)
        if not merchant_id:
            return Response({'error': '缺少必传参数'}, status=status.HTTP_400_BAD_REQUEST)
        merchant = self.get_queryset().filter(id=merchant_id).first()
        if not merchant:
            return Response({'error': '无效商户id'}, status=status.HTTP_400_BAD_REQUEST)
        if merchant.is_mall != 0:
            return Response({'error': '商户商圈状态有误'}, status=status.HTTP_400_BAD_REQUEST)
        '''校验商户当前通道'''
        try:
            url = 'https://api.gdwxyf.com/api/searchmerchantmsg.do'
            key = '6715C7D4435343BA0459EAEC2334D81B'
            body = {
                "program_id": "202316837141378884",
                "shop_id": merchant.wyfMerchantID
            }
            sign = get_sign(body, key)
            body['sign'] = sign
            response = requests.post(url=url, json=body)
            result = response.json()
            if result['pay_type'] != 'sxf_tq':
                return Response({'error': '商户通道不支持入驻商圈'}, status=status.HTTP_400_BAD_REQUEST)
        except:
            pass
        # check_merhant_channel = MerchantChannel.objects.filter(merchant_id=merchant_id, channel_id=3)
        # if not check_merhant_channel:
        if merchant.channel_id != 3:
            return Response({'error': '商户通道不支持入驻商圈'}, status=status.HTTP_400_BAD_REQUEST)
        '''商户授权应用id'''
        url = 'https://api.gdwxyf.com/api/shopBindApp.do'
        key = '6715C7D4435343BA0459EAEC2334D81B'
        body = {
            "program_id": "202316837141378884",
            "shop_id": merchant.wyfMerchantID
        }
        sign = get_sign(body, key)
        body['sign'] = sign
        response = requests.post(url=url, json=body)
        result = response.json()
        if result['result_code'] != 'success' and result['error_msg'] != '商户与应用已绑定，请勿重复绑定。':
            return Response({'error': result['error_msg']}, status=status.HTTP_400_BAD_REQUEST)
        '''商户绑定授权appid'''
        url = 'https://api.gdwxyf.com/api/setMerchantWxAppMsg.do'
        body = {
            "program_id": "202316837141378884",
            "shop_id": merchant.ruiyinxinMerchantID,
            "config_type": 'appid',
            "appid": "wx950122ad80dc97c9"
        }
        sign = get_sign(body, key)
        body['sign'] = sign
        response = requests.post(url=url, json=body)
        result = response.json()
        if result['result_code'] != 'success' and result['error_msg'] != '微信公众号配置已配置':
            return Response({'error': result['error_msg']}, status=status.HTTP_400_BAD_REQUEST)
        merchant.is_mall = 1
        merchant.save()
        return Response({'success': '操作成功'}, status=status.HTTP_200_OK)

    def confirm_is_mall(self, request):
        user = self.request.iser
        merchant_id = self.request.data.get('merchant_id', None)
        reject_reason = self.request.data.get('reject_reason', None)
        applyment_state = self.request.data.get('applyment_state', None)
        datetime_now = datetime.datetime.now()
        if not merchant_id:
            return Response({'error': '缺少必传参数'}, status=status.HTTP_400_BAD_REQUEST)
        merchant = self.get_queryset().filter(id=merchant_id).first()
        if not merchant:
            return Response({'error': '无效商户id'}, status=status.HTTP_400_BAD_REQUEST)
        if merchant.is_mall != 5:
            return Response({'error': '商户商圈状态有误'}, status=status.HTTP_400_BAD_REQUEST)
        mall_applyment = MerchantMallApplyment.objects.filter(merchant_id=merchant.id, applyment_type=1).last()
        if str(applyment_state) == '1':
            # if merchant.applyment_state == 5:
            #     store_indoor_copy = MerchantImage.objects.filter(merchant_id=merchant.id).first()
            #     if not store_indoor_copy:
            #         store_indoor_copy = merchant.store_header_copy.url
            #     else:
            #         store_indoor_copy = store_indoor_copy.image.url
            #     result = submit_sign_contract(merchant.ruiyinxinMerchantID, mall_applyment.contract.url, merchant.store_header_copy.url, store_indoor_copy)
            #     if result['data']['sign_status'] == 1:
            #         merchant.applyment_state = 4
            #         merchant.save()
            #         mall_applyment.applyment_state = 4
            #         signUrl = result['data']['sign_url']
            #         sign_url = make_qrcode1(merchant.ruiyinxinMerchantID, signUrl, key=None)
            #         mall_applyment.sign_url = sign_url
            #         mall_applyment.save()
            #         return Response({'success': '提交资料成功,等待审核'}, status=status.HTTP_200_OK)
            #     else:
            #         return Response({'error': result['data']['message']}, status=status.HTTP_400_BAD_REQUEST)
            # else:
            #     if merchant.applyment_state != 2:
            #         return Response({'error': '请等待商户签约完成再审核'}, status=status.HTTP_400_BAD_REQUEST)
            try:
                '''创建门店'''
                url = 'https://manage.gdwxyf.com/internal/savebranchstoremsg.do'
                body = {
                    "deviceName": "微邮惠商圈",
                    "shopId": merchant.wyfMerchantID,
                    "account": "gdyouzheng"
                }
                response = requests.post(url=url, data=body)
                result = response.json()
                device_id = result['device_id']
                '''绑定设备id'''
                url = 'https://manage.gdwxyf.com/internal/savenewqrcode.do'
                body = {
                    "deviceName": "微邮惠商圈",
                    "shopId": merchant.wyfMerchantID,
                    "wsyDeviceId": f'{merchant.wyfMerchantID}2024',
                    "deviceId": device_id
                }
                response = requests.post(url=url, data=body)
                result = response.json()
                if result['result_code'] == 'fail':
                    return Response({'error': result['error_msg']}, status=status.HTTP_400_BAD_REQUEST)
            except:
                return Response({'error': '创建门店失败,请联系管理员'}, status=status.HTTP_400_BAD_REQUEST)
            merchant.is_mall = 2
            merchant.device = f'{merchant.wyfMerchantID}2024'
            merchant.applyment_state = 2
            merchant.verify_state = 2
            merchant.is_profit_share = 4
            merchant.save()
            if mall_applyment:
                mall_applyment.applyment_state = 2
                mall_applyment.audit_time = datetime_now
                mall_applyment.verify_state = 2
                mall_applyment.verify_time = datetime_now
                mall_applyment.verify_user_id = user.id
                mall_applyment.save()
            return Response({'success': '审核成功'}, status=status.HTTP_200_OK)
        elif str(applyment_state) == '2':
            merchant.is_mall = 1
            merchant.applyment_state = 3
            merchant.save()
            if mall_applyment:
                mall_applyment.applyment_state = 3
                mall_applyment.audit_time = datetime_now
                mall_applyment.reject_reason = reject_reason
                mall_applyment.verify_user_id = user.id
                mall_applyment.save()
            return Response({'success': '驳回成功'}, status=status.HTTP_200_OK)
        else:
            return Response({'error': '审核参数有误'}, status=status.HTTP_400_BAD_REQUEST)


class MerchantBusinessCategoryModelViewSet(ModelViewSet):

    queryset = MerchantBusinessCategory.objects.all()
    serializer_class = MerchantBusinessCategoryModelSerializer


class LaunchedGoodsModelViewSet(ModelViewSet):
    '''商品'''

    pagination_class = MyPage
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)
    search_fields = ('name', 'goods__merchant__name', 'level__account', 'level__name')
    filter_class = LaunchedGoodsFilter

    def get_serializer_class(self):
        if self.action == 'list':
            return LaunchedGoodsListModelSerializer
        else:
            return LaunchedGoodsListModelSerializer

    def get_queryset(self):
        user = self.request.iser
        level = user.level
        level_id = self.request.query_params.get('level', None)
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        if level.level == 0:
            queryset = LaunchedGoods.objects.all().order_by('-create_time')
        elif level.level == 1:
            queryset = LaunchedGoods.objects.filter(level__prov_id=level.id).order_by('-create_time')
        elif level.level == 2:
            queryset = LaunchedGoods.objects.filter(level__city_id=level.id).order_by('-create_time')
        elif level.level == 3:
            queryset = LaunchedGoods.objects.filter(level__district_id=level.id).order_by('-create_time')
        else:
            queryset = LaunchedGoods.objects.filter(level__branch_id=level.id).order_by('-create_time')
        return queryset

    def create(self, request, *args, **kwargs):
        goods_id = self.request.data.get('goods_id', None)
        launchedgoods_array = self.request.data.get('launchedgoods_array', None)
        if not all([goods_id, launchedgoods_array]):
            return Response({'error': '缺少必传参数'}, status=status.HTTP_400_BAD_REQUEST)
        if not isinstance(launchedgoods_array, list):
            return Response({'error': '参数格式有误'}, status=status.HTTP_400_BAD_REQUEST)
        with transaction.atomic():
            save_id = transaction.savepoint()
            try:
                while True:
                    try:
                        goods = Goods.objects.get(id=goods_id)
                    except:
                        transaction.savepoint_rollback(save_id)
                        return Response({'error': '无效商品id'}, status=status.HTTP_400_BAD_REQUEST)
                    origin_remain_stock = goods.remain_stock
                    count = 0
                    for launchedgoods in launchedgoods_array:
                        launchedgoods_data = {}
                        launchedgoods_data['level_id'] = launchedgoods['level_id']
                        launchedgoods_data['stock'] = launchedgoods['stock']
                        launchedgoods_data['goods_id'] = goods_id
                        launchedgoods_data['create_time'] = datetime.datetime.now()
                        launchedgoods_data['price'] = goods.price
                        launchedgoods_data['category_id'] = goods.category_id
                        instance, create = LaunchedGoods.objects.get_or_create(defaults=launchedgoods_data, level_id=launchedgoods_data['level_id'], goods_id=goods_id)
                        if create:
                            count += int(launchedgoods['stock'])
                    new_remain_stock = origin_remain_stock + count
                    result = Goods.objects.filter(id=instance.goods_id, remain_stock=origin_remain_stock).update(remain_stock=new_remain_stock)
                    if result == 0:
                        continue
                    break
            except Exception as e:
                logger.error(e)
                # 事务回滚
                transaction.savepoint_rollback(save_id)
                return Response({'error': '上架成失败'}, status=status.HTTP_400_BAD_REQUEST)
            transaction.savepoint_commit(save_id)
            return Response({'success': '上架成功'}, status=status.HTTP_200_OK)

    def update(self, request, *args, **kwargs):
        instance = self.get_object()
        stock = self.request.data.get('stock', None)
        if not stock:
            return Response({'error': '缺少必传参数'}, status=status.HTTP_400_BAD_REQUEST)
        try:
            stock = int(stock)
        except:
            return Response({'error': '库存参数格式有误, 请输入整数型'}, status=status.HTTP_400_BAD_REQUEST)
        with transaction.atomic():
            save_id = transaction.savepoint()
            try:
                while True:
                    instance = LaunchedGoods.objects.get(id=instance.id)
                    goods = Goods.objects.get(id=instance.goods_id)
                    origin_remain_stock = goods.remain_stock
                    launched_origin_stock = instance.stock
                    change_stock = launched_origin_stock - stock
                    new_remain_stock = origin_remain_stock - change_stock
                    launched_result = LaunchedGoods.objects.filter(id=instance.id, stock=launched_origin_stock).update(stock=stock)
                    result = Goods.objects.filter(id=instance.goods_id, remain_stock=origin_remain_stock).update(remain_stock=new_remain_stock)
                    if result == 0:
                        continue
                    if launched_result == 0:
                        continue
                    break
            except Exception as e:
                logger.error(e)
                # 事务回滚
                transaction.savepoint_rollback(save_id)
                return Response({'error': '修改失败'}, status=status.HTTP_400_BAD_REQUEST)
            transaction.savepoint_commit(save_id)
            return Response({'success': '修改成功'}, status=status.HTTP_200_OK)

    def partial_update(self, request, *args, **kwargs):
        instance = self.get_object()
        is_launched = self.request.data.get('is_launched', None)
        if not is_launched:
            return Response({'error': '缺少必传参数'}, status=status.HTTP_400_BAD_REQUEST)
        if str(is_launched) not in ['0', '1']:
            return Response({'error': '参数有误'}, status=status.HTTP_400_BAD_REQUEST)
        if str(is_launched) == '0':
            instance.is_launched = 0
            instance.save()
            return Response({'success': '下架成功'}, status=status.HTTP_200_OK)
        else:
            instance.is_launched = 1
            instance.save()
            return Response({'success': '上架成功'}, status=status.HTTP_200_OK)


class GoodsCategoryModelViewSet(ModelViewSet):

    serializer_class = GoodsCategoryModelSerializer
    queryset = GoodsCategory.objects.all()
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)
    search_fields = ('name', )


class GoodsModelViewSet(ModelViewSet):
    '''商品'''

    pagination_class = MyPage
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)
    search_fields = ('name', )
    filter_class = GoodsFilter

    def get_serializer_class(self):
        if self.action == 'list':
            return GoodsListModelSerializer
        else:
            return GoodsRetrieveModelSerializer

    def get_queryset(self):
        user = self.request.iser
        level = user.level
        level_id = self.request.query_params.get('level', None)
        is_newyear = self.request.query_params.get('is_newyear', '')
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        if str(is_newyear) == '1':
            queryset = Goods.objects.filter(goods_tag='gdnhj')
            if level.level == 0:
                pass
            elif level.level == 1:
                queryset = queryset.filter(merchant__level__prov_id=level.id)
            elif level.level == 2:
                queryset = queryset.filter(merchant__level__city_id=level.id)
            elif level.level == 3:
                queryset = queryset.filter(merchant__level__district_id=level.id)
            else:
                queryset = queryset.filter(merchant__level__branch_id=level.id)
            return queryset.order_by('-id')
        else:
            if level.level == 0:
                queryset = Goods.objects.all().order_by('-id')
            elif level.level == 1:
                queryset = Goods.objects.filter(launchedgoods__level__prov_id=level.id).distinct().order_by('-id')
            elif level.level == 2:
                queryset = Goods.objects.filter(launchedgoods__level__city_id=level.id).distinct().order_by('-id')
            elif level.level == 3:
                queryset = Goods.objects.filter(launchedgoods__level__district_id=level.id).distinct().order_by('-id')
            else:
                queryset = Goods.objects.filter(launchedgoods__level__branch_id=level.id).distinct().order_by('-id')
            return queryset.filter(equityID__isnull=True)

    def upload_image(self, request):
        user = self.request.iser
        img = self.request.FILES.get('img', None)
        merchant_id = self.request.data.get('merchant_id', None)
        if not all([img, merchant_id]):
            return Response({'error': '缺少必传参数'}, status=status.HTTP_400_BAD_REQUEST)
        if img.size > 2097152:
            return Response({'error': '照片不得超过2M,请重新上传!'}, status=status.HTTP_400_BAD_REQUEST)
        img_str = img.read()
        img.seek(0)
        try:
            merchant = Merchant.objects.get(id=merchant_id)
        except:
            return Response({'error': '无效商户号'}, status=status.HTTP_400_BAD_REQUEST)
        try:
            img_id = f'youhuiquanyi/{merchant.wyfMerchantID}/goods_image{"%06d" % randint(0, 999999)}.png'
            mid_img = pic_upload(img_str, key=img_id)
        except Exception as e:
            logger.error(e)
            return Response({'error': '图片上传失败,请重新上传!'}, status=status.HTTP_400_BAD_REQUEST)
        return Response({'success': '操作成功', 'img_id': f'https://circle.sutpay.cn/{img_id}'}, status=status.HTTP_200_OK)

    def create(self, request, *args, **kwargs):
        user = self.request.iser
        name = self.request.data.get('name', None)
        caption = self.request.data.get('caption', None)
        desc_detail = self.request.data.get('desc_detail', None)
        price = self.request.data.get('price', None)
        market_price = self.request.data.get('market_price', None)
        default_image = self.request.data.get('default_image', None)
        image_array = self.request.data.get('image_array', None)
        merchant_id = self.request.data.get('merchant_id', None)
        manufacturer = self.request.data.get('manufacturer', None)
        specifications = self.request.data.get('specifications', None)
        category_id = self.request.data.get('category_id', None)
        if not all([name, caption, desc_detail, price, market_price, default_image, image_array, merchant_id, manufacturer, specifications, category_id]):
            return Response({'error': '缺少必传参数'}, status=status.HTTP_400_BAD_REQUEST)
        try:
            desc_detail = json.dumps(desc_detail)
            # image_array = json.dumps(image_array)
        except:
            return Response({'error': '商品详情数据格式有误'}, status=status.HTTP_400_BAD_REQUEST)
        try:
            category = GoodsCategory.objects.get(id=category_id)
        except:
            return Response({'error': '无效商品类别参数'}, status=status.HTTP_400_BAD_REQUEST)
        try:
            merchant = Merchant.objects.get(id=merchant_id)
        except:
            return Response({'error': '无效商户id'}, status=status.HTTP_400_BAD_REQUEST)
        goods_data = {}
        goods_data['name'] = name
        goods_data['caption'] = caption
        goods_data['desc_detail'] = desc_detail
        goods_data['price'] = price
        goods_data['market_price'] = market_price
        goods_data['default_image'] = default_image.replace('https://circle.sutpay.cn/', '')
        goods_data['merchant_id'] = merchant_id
        goods_data['manufacturer'] = manufacturer
        goods_data['specifications'] = specifications
        goods_data['is_launched'] = 2
        goods_data['category_id'] = category_id
        goods_data['order_species'] = 2
        try:
            goods = Goods.objects.create(**goods_data)
            for image in image_array:
                GoodsImage.objects.create(
                    goods_id=goods.id,
                    image = image.replace('https://circle.sutpay.cn/', '')
                )
            try:
                GoodsAuditRecord.objects.create(
                    goods_id=goods.id,
                    create_user_id=user.id,
                    audit_type=1,
                    remark="新增商品"
                )
            except:
                pass
            return Response({'success': '创建成功', 'goods_id': goods.id}, status=status.HTTP_200_OK)
        except Exception as e:
            return Response({'error': '创建失败.请联系管理员'}, status=status.HTTP_400_BAD_REQUEST)

    def update(self, request, *args, **kwargs):
        instance = self.get_object()
        name = self.request.data.get('name', None)
        caption = self.request.data.get('caption', None)
        desc_detail = self.request.data.get('desc_detail', None)
        price = self.request.data.get('price', None)
        market_price = self.request.data.get('market_price', None)
        default_image = self.request.data.get('default_image', None)
        image_array = self.request.data.get('image_array', None)
        manufacturer = self.request.data.get('manufacturer', None)
        specifications = self.request.data.get('specifications', None)
        if not all([name, caption, desc_detail, price, market_price, default_image, image_array, manufacturer, specifications]):
            return Response({'error': '缺少必传参数'}, status=status.HTTP_400_BAD_REQUEST)
        try:
            desc_detail = json.dumps(desc_detail)
            # image_array = json.dumps(image_array)
        except:
            return Response({'error': '商品详情数据格式有误'}, status=status.HTTP_400_BAD_REQUEST)
        try:
            instance.name = name
            instance.caption = caption
            instance.desc_detail = desc_detail
            instance.price = price
            instance.market_price = market_price
            instance.default_image = default_image.replace('https://circle.sutpay.cn/', '')
            instance.manufacturer = manufacturer
            instance.specifications = specifications
            instance.save()
            GoodsImage.objects.filter(goods_id=instance.id).delete()
            for image in image_array:
                GoodsImage.objects.create(
                    goods_id=instance.id,
                    image = image.replace('https://circle.sutpay.cn/', '')
                )
            return Response({'success': '编辑商品成功'}, status=status.HTTP_200_OK)
        except:
            return Response({'error': '编辑商品失败'}, status=status.HTTP_400_BAD_REQUEST)

    def applyment(self, request):
        return Response({'error': '功能已取消'}, status=status.HTTP_400_BAD_REQUEST)
        applyment_id = self.request.data.get('applyment_id')
        reject_reason = self.request.data.get('reject_reason', None)
        applyment_status = self.request.data.get('applyment_status', None)
        if not applyment_id:
            return Response({'error': '缺少申请单参数'}, status=status.HTTP_400_BAD_REQUEST)
        if str(applyment_status) not in ['1', '2']:
            return Response({'error': '审核状态参数有误'}, status=status.HTTP_400_BAD_REQUEST)
        try:
            applyment = GoodsModifyApplyment.objects.get(id=applyment_id)
        except:
            return Response({'error': '无效申请单id'}, status=status.HTTP_400_BAD_REQUEST)
        if applyment.applyment_status != 1:
            return Response({'error': '申请单状态有误,请勿重复操作'}, status=status.HTTP_400_BAD_REQUEST)
        goods = applyment.goods
        launched_goods = LaunchedGoods.objects.filter(goods_id=goods.id, level_id=applyment.level_id).first()
        if str(applyment_status) == '2':
            if not reject_reason:
                return Response({'error': '请输入驳回原因'}, status=status.HTTP_400_BAD_REQUEST)
            if applyment.applyment_type == 1:
                applyment.applyment_status = 3
                applyment.reject_reason = reject_reason
                applyment.save()
                goods.is_launched = 3
                if applyment.update_word:
                    update_word = json.loads(applyment.update_word)
                    for word in update_word:
                        if word == 'name':
                            goods.name = applyment.name
                        elif word == 'desc_detail':
                            goods.desc_detail = applyment.desc_detail
                        elif word == 'price':
                            goods.price = applyment.price
                        elif word == 'default_image':
                            default_image = applyment.default_image.__str__()
                            goods.default_image = default_image.replace('https://circle.sutpay.cn', '')
                        elif word == 'manufacturer':
                            goods.manufacturer = applyment.manufacturer
                        elif word == 'specifications':
                            goods.specifications = applyment.specifications
                        elif word == 'market_price':
                            goods.market_price = applyment.market_price
                        elif word == 'caption':
                            goods.caption = applyment.caption
                        elif word == 'goodsimage_set':
                            goodsimage_set = goods.goodsimage_set.all().delete()
                            image_array = json.loads(applyment.image_array)
                            for image in image_array:
                                GoodsImage.objects.create(
                                    goods_id=goods.id,
                                    image=image.replace('https://circle.sutpay.cn/', '')
                                )
                goods.save()
            else:
                applyment.applyment_status = 3
                applyment.reject_reason = reject_reason
                applyment.save()
                goods.is_launched = 3
                goods.save()
        elif str(applyment_status) == '1':
            if applyment.applyment_type == 1:
                applyment.applyment_status = 2
                applyment.save()
                goods.remain_stock = goods.remain_stock + launched_goods.stock - applyment.stock
                goods.is_launched = 1
                goods.save()
            else:
                applyment.applyment_status = 2
                applyment.save()
                goods.remain_stock = goods.remain_stock + launched_goods.stock - applyment.stock
                goods.is_launched = 1
                goods.save()
                merchantenter_set = goods.merchant.merchantenter_set.all()
                for merchantenter in merchantenter_set:
                    launchedgoods_data = {}
                    launchedgoods_data['level_id'] = merchantenter.level_id
                    launchedgoods_data['goods_id'] = goods.id
                    launchedgoods_data['is_launched'] = 0
                    launchedgoods_data['name'] = goods.name
                    launchedgoods_data['category_id'] = 1
                    launchedgoods_data['stock'] = 0
                    LaunchedGoods.objects.get_or_create(defaults=launchedgoods_data, level_id=merchantenter.level_id, goods_id=goods.id)
        else:
            return Response({'error': '审核状态参数有误'}, status=status.HTTP_200_OK)
        try:
            expedite_applyment_send.delay({'id': applyment.id})
        except:
            pass
        return Response({'success': '操作成功'}, status=status.HTTP_200_OK)

    def partial_update(self, request, *args, **kwargs):
        instance = self.get_object()
        if instance.is_launched not in [0, 1]:
            return Response({'error': '商品状态有误,无法操作'}, status=status.HTTP_400_BAD_REQUEST)
        is_launched = self.request.data.get('is_launched', None)
        if not is_launched:
            return Response({'error': '缺少必传参数'}, status=status.HTTP_400_BAD_REQUEST)
        if str(is_launched) not in ['0', '1']:
            return Response({'error': '参数有误'}, status=status.HTTP_400_BAD_REQUEST)
        if str(is_launched) == '0':
            instance.is_launched = 0
            instance.save()
            return Response({'success': '下架成功'}, status=status.HTTP_200_OK)
        else:
            instance.is_launched = 1
            instance.save()
            return Response({'success': '上架成功'}, status=status.HTTP_200_OK)

    def first_audit(self, request):
        user = self.request.iser
        if user.role_id == 3:
            return Response({'error': '您无权限审核,请联系区县管理员审核'}, status=status.HTTP_400_BAD_REQUEST)
        if user.level.level == 4:
            return Response({'error': '您无权限审核,请联系区县管理员审核'}, status=status.HTTP_400_BAD_REQUEST)
        goods_id = self.request.data.get('goods_id', None)
        audit_state = self.request.data.get('audit_state', None)
        reject_reason = self.request.data.get('reject_reason', None)
        if not goods_id:
            return Response({'error': '请上传商品id'}, status=status.HTTP_400_BAD_REQUEST)
        try:
            goods = self.get_queryset().get(id=goods_id)
        except:
            return Response({'error': '无效商品id'}, status=status.HTTP_400_BAD_REQUEST)
        if str(audit_state) not in ['1', '2']:
            return Response({'error': '无效审核参数'}, status=status.HTTP_400_BAD_REQUEST)
        if goods.is_launched != 4:
            return Response({'error': '商品状态有误'}, status=status.HTTP_400_BAD_REQUEST)
        if str(audit_state) == '1':
            goods.is_launched = 2
            goods.save()
            remark = '区县管理员审核商品(通过)'
        else:
            applyment = GoodsModifyApplyment.objects.filter(applyment_type=2, goods_id=goods.id, applyment_status=1).first()
            if applyment:
                applyment.applyment_status = 3
                applyment.reject_reason = reject_reason
                applyment.save()
            goods.is_launched = 3
            goods.save()
            remark = '区县管理员审核商品(驳回)'
        try:
            GoodsAuditRecord.objects.create(
                goods_id=goods.id,
                create_user_id=user.id,
                audit_type=2,
                remark=remark
            )
        except:
            pass
        return Response({'success': '操作成功'}, status=status.HTTP_200_OK)

    def batch_update_goods_stock(self, reqeust):
        update_type = self.request.data.get('update_type', '1')
        goods_id = self.request.data.get('goods_id', None)
        stock = self.request.data.get('stock', None)
        if not stock:
            return Response({'error': '缺少必传参数'}, status=status.HTTP_400_BAD_REQUEST)
        try:
            goods = self.get_queryset().get(id=goods_id)
        except:
            return Response({'error': '无效商品id'}, status=status.HTTP_400_BAD_REQUEST)
        stock = int(stock)
        if str(update_type) == '1':
            if int(stock) < 0:
                return Response({'error': '调整库存不得小于0'}, status=status.HTTP_400_BAD_REQUEST)
        else:
            if int(stock) <= 0:
                return Response({'error': '增加库存须大于0'}, status=status.HTTP_400_BAD_REQUEST)
        user = self.request.iser
        level = user.level
        if level.level == 0:
            launchedgoods_set = LaunchedGoods.objects.filter(goods_id=goods_id)
        elif level.level == 1:
            launchedgoods_set = LaunchedGoods.objects.filter(level__prov_id=level.id, goods_id=goods_id)
        elif level.level == 2:
            launchedgoods_set = LaunchedGoods.objects.filter(level__city_id=level.id, goods_id=goods_id)
        elif level.level == 3:
            launchedgoods_set = LaunchedGoods.objects.filter(level__district_id=level.id, goods_id=goods_id)
        else:
            launchedgoods_set = LaunchedGoods.objects.filter(level__branch_id=level.id, goods_id=goods_id)
        for launchedgoods in launchedgoods_set:
            launchedgoods_id = launchedgoods.id
            while True:
                launchedgoods = LaunchedGoods.objects.get(id=launchedgoods_id)
                launched_origin_stock = launchedgoods.stock
                if str(update_type) == '1':
                    change_stock = launched_origin_stock - stock
                else:
                    change_stock = -stock
                new_stock = launched_origin_stock - change_stock
                launched_result = LaunchedGoods.objects.filter(id=launchedgoods_id, stock=launched_origin_stock).update(stock=new_stock)
                if launched_result == 0:
                    continue
                break
            while True:
                goods = Goods.objects.get(id=goods_id)
                origin_remain_stock = goods.remain_stock
                origin_stock = goods.stock
                new_remain_stock = origin_remain_stock - change_stock
                new_stock = origin_stock - change_stock
                result = Goods.objects.filter(id=goods_id, remain_stock=origin_remain_stock).update(remain_stock=new_remain_stock, stock=new_stock)
                if result == 0:
                    continue
                break
        return Response({'success': '操作成功'}, status=status.HTTP_200_OK)


class OrderInfoModelViewSet(ModelViewSet):
    '''订单'''

    pagination_class = MyPage
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)
    # search_fields = ('merchant__name', 'ordergoods__goods__name', 'customer_user__mobile')
    filter_class = OrderInfoFilter

    def get_serializer_class(self):
        if self.action == 'list':
            return OrderInfoListModelSerializer
        else:
            return OrderInfoRetrieveModelSerializer

    def get_queryset(self):
        user = self.request.iser
        level = user.level
        level_id = self.request.query_params.get('level', None)
        search = self.request.query_params.get('search', None)
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        if user.role_id == 3:
            if level.level == 0:
                queryset = OrderInfo.objects.all().order_by('-create_time')
            elif level.level == 1:
                queryset = OrderInfo.objects.filter(level__prov_id=level.id).order_by('-create_time')
            elif level.level == 2:
                queryset = OrderInfo.objects.filter(level__city_id=level.id).order_by('-create_time')
            elif level.level == 3:
                queryset = OrderInfo.objects.filter(level__district_id=level.id).order_by('-create_time')
            else:
                queryset = OrderInfo.objects.filter(level__branch_id=level.id).order_by('-create_time')
        else:
            if level.level == 0:
                queryset = OrderInfo.objects.all().order_by('-create_time')
            elif level.level == 1:
                queryset = OrderInfo.objects.filter(merchant__level__prov_id=level.id).order_by('-create_time')
            elif level.level == 2:
                queryset = OrderInfo.objects.filter(merchant__level__city_id=level.id).order_by('-create_time')
            elif level.level == 3:
                queryset = OrderInfo.objects.filter(merchant__level__district_id=level.id).order_by('-create_time')
            else:
                queryset = OrderInfo.objects.filter(merchant__level__branch_id=level.id).order_by('-create_time')
        queryset = queryset.filter(create_time__gte="2023-01-01 00:00:00")
        if search:
            es = Elasticsearch(["http://159.75.55.19:9200/"])
            body = {
                "query": {
                    "bool": {
                        "must": [],
                        "must_not": [],
                        "should": []
                    }
                },
                "from": 0,
                "size": 10000,
                "sort": [],
                "aggs": {}
            }
            if not search.isdigit():
                filter_data = {
                    "match_phrase_prefix": {
                        "text": search
                    }
                }
                body['query']['bool']['must'].append(filter_data)
            else:
                filter_data = {
                    "wildcard": {
                        "text": f'*{search}*'
                    }
                }
                body['query']['bool']['must'].append(filter_data)
            body['query']['bool']['must_not'].append({"wildcard": {"text": "*vm*"}})
            result = es.search(index="equity_mall_order", doc_type="modelresult", body=body)
            # return Response(result)
            hits = result['hits']['hits']
            id_list = []
            for order in hits:
                id_list.append(order['_id'])
            queryset = queryset.filter(id__in=id_list)
        return queryset

    def export_orderinfo(self, request):
        user = self.request.iser
        level = user.level
        level_id = self.request.query_params.get('level', None)
        create_time_begin = self.request.query_params.get('create_time_begin', None)
        create_time_end = self.request.query_params.get('create_time_end', None)
        total_price_min = self.request.query_params.get('total_price_min', None)
        total_price_max = self.request.query_params.get('total_price_max', None)
        state = self.request.query_params.get('state', None)
        search = self.request.query_params.get('search', None)
        order_species = self.request.query_params.get('order_species', None)
        goods_id = self.request.query_params.get('goods_id', None)
        customeruser_mobile = self.request.query_params.get('customeruser_mobile', None)
        merchant_id = self.request.query_params.get('merchant_id', None)
        customeruser_id = self.request.query_params.get('customeruser_id', None)
        payment_time_begin = self.request.query_params.get('payment_time_begin', None)
        payment_time_end = self.request.query_params.get('payment_time_end', None)
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        if user.role_id == 3:
            if level.level == 0:
                condition = 'WHERE id!=1'
            elif level.level == 1:
                condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE prov_id={level.id})'
            elif level.level == 2:
                condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE city_id={level.id})'
            elif level.level == 3:
                condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE district_id={level.id})'
            else:
                condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE branch_id={level.id})'
        else:
            if level.level == 0:
                condition = 'WHERE id!=1'
            elif level.level == 1:
                condition = f'WHERE merchant_id IN (SELECT id FROM tb_merchant WHERE level_id IN (SELECT id FROM tb_u_level WHERE prov_id={level.id}))'
            elif level.level == 2:
                condition = f'WHERE merchant_id IN (SELECT id FROM tb_merchant WHERE level_id IN (SELECT id FROM tb_u_level WHERE city_id={level.id}))'
            elif level.level == 3:
                condition = f'WHERE merchant_id IN (SELECT id FROM tb_merchant WHERE level_id IN (SELECT id FROM tb_u_level WHERE district_id={level.id}))'
            else:
                condition = f'WHERE merchant_id IN (SELECT id FROM tb_merchant WHERE level_id IN (SELECT id FROM tb_u_level WHERE branch_id={level.id}))'
        if search:
            es = Elasticsearch(["http://159.75.55.19:9200/"])
            body = {
                "query": {
                    "bool": {
                        "must": [],
                        "must_not": [],
                        "should": []
                    }
                },
                "from": 0,
                "size": 10000,
                "sort": [],
                "aggs": {}
            }
            if not search.isdigit():
                filter_data = {
                    "match_phrase_prefix": {
                        "text": search
                    }
                }
                body['query']['bool']['must'].append(filter_data)
            else:
                filter_data = {
                    "wildcard": {
                        "text": f'*{search}*'
                    }
                }
                body['query']['bool']['must'].append(filter_data)
            body['query']['bool']['must_not'].append({"wildcard": {"text": "*vm*"}})
            result = es.search(index="equity_mall_order", doc_type="modelresult", body=body)
            # return Response(result)
            hits = result['hits']['hits']
            id_list = []
            for order in hits:
                id_list.append(order['_id'])
            if id_list:
                if len(id_list) == 1:
                    condition = condition + f' AND id IN {tuple(id_list)}'.replace(',', '')
                else:
                    condition = condition + f' AND id IN {tuple(id_list)}'
        if create_time_begin:
            condition = condition + f' AND create_time >= "{create_time_begin + " 00:00:00"}"'
        if create_time_end:
            condition = condition + f' AND create_time <= "{create_time_end + " 23:59:59"}"'
        if payment_time_begin:
            condition = condition + f' AND payment_time >= "{payment_time_begin + " 00:00:00"}"'
        if payment_time_end:
            condition = condition + f' AND payment_time <= "{payment_time_end + " 23:59:59"}"'
        if total_price_min:
            condition = condition + f' AND total_price >= "{total_price_min}"'
        if total_price_max:
            condition = condition + f' AND total_price <= "{total_price_max}"'
        if state:
            condition = condition + f' AND state in ({state})'
        if customeruser_mobile:
            condition = condition + f' AND customeruservice_id IN (SELECT id FROM tb_u_customer_user_vice WHERE mobile="{customeruser_mobile}")'
        if order_species:
            condition = condition + f' AND order_species in ({order_species})'
        if merchant_id:
            condition = condition + f' AND merchant_id={merchant_id}'
        if customeruser_id:
            condition = condition + f' AND customer_user_id={customeruser_id}'
        condition = condition + f' AND create_time >= "2023-01-01 00:00:00"'
        conn = pymysql.connect(host=settings.DATABASES['default']['HOST'],
                               port=settings.DATABASES['default']['PORT'],
                               database=settings.DATABASES['default']['NAME'],
                               user=settings.DATABASES['default']['USER'],
                               password=settings.DATABASES['default']['PASSWORD'])
        cursor = conn.cursor(cursor=pymysql.cursors.SSDictCursor)
        # try:
        #     sql = f'''
        #     SELECT t.*,u.merchant_level FROM (SELECT * FROM (SELECT p.*,q.account,level_name,merchant_name,wyfMerchantID FROM (SELECT l.*,m.goods_name,goods_count,goods_price FROM (SELECT g.*,h.coupons_id,coupons_status,coupons_use_time FROM (SELECT c.*,d.customer_level,mobile,realname FROM (SELECT a.*, b.name FROM (SELECT id,level_id,state,total_price,total_point,(total_price-realpay_amount)AS coupons_amount,realpay_amount,customer_user_id,orderNum,DATE_FORMAT(create_time,'%Y-%m-%d %H:%i:%S') AS create_time,merchant_id,order_id,trade_no FROM tb_order_info {condition})AS a LEFT JOIN (SELECT id,name FROM tb_u_level)AS b ON a.level_id=b.id)AS c LEFT JOIN (SELECT e.*,f.customer_level FROM (SELECT id,mobile,realname,level_id FROM tb_u_customer_user)AS e LEFT JOIN (SELECT id,CONCAT(prov_name,'-',city_name,'-',district_name,'-',branch_name)AS customer_level FROM tb_u_level)AS f ON e.level_id=f.id)AS d ON c.customer_user_id=d.id)AS g LEFT JOIN (SELECT GROUP_CONCAT(coupons_id)AS coupons_id,GROUP_CONCAT(status)AS coupons_status,GROUP_CONCAT(DATE_FORMAT(use_time,'%Y-%m-%d %H:%i:%S'))AS coupons_use_time,order_id FROM tb_goods_coupons WHERE order_id IN (SELECT id FROM tb_order_info {condition}) GROUP BY order_id)AS h ON g.id=h.order_id)AS l LEFT JOIN (SELECT GROUP_CONCAT(k.name)AS goods_name,GROUP_CONCAT(k.count)AS goods_count,GROUP_CONCAT(k.price)AS goods_price,order_id FROM (SELECT i.price,count,order_id,j.name FROM (SELECT * FROM tb_order_goods WHERE order_id IN (SELECT id FROM tb_order_info {condition}))AS i LEFT JOIN (SELECT * FROM tb_goods)AS j ON i.goods_id=j.id)AS k GROUP BY order_id)AS m ON l.id=m.order_id)AS p LEFT JOIN (SELECT n.*,o.account,level_name FROM (SELECT id,name AS merchant_name,wyfMerchantID,level_id FROM tb_merchant)AS n LEFT JOIN (SELECT id,name AS level_name,account FROM tb_u_level)AS o ON n.level_id=o.id)AS q ON p.merchant_id=q.id)AS r LEFT JOIN (SELECT managermobile,wyfMerchantID AS business_no,short_name,level_id AS merchant_level_id FROM tb_merchant)AS s ON r.mobile=s.managermobile)AS t LEFT JOIN(SELECT id,CONCAT(prov_name,'-',city_name,'-',district_name,'-',branch_name)AS merchant_level FROM tb_u_level)AS u ON t.merchant_level_id=u.id;
        #     '''
        #     cursor.execute(sql)
        # except Exception as e:
        #     sql = f'''
        #     SELECT p.*,q.account,level_name,merchant_name,wyfMerchantID FROM (SELECT l.*,m.goods_name,goods_count,goods_price FROM (SELECT g.*,h.coupons_id,coupons_status,coupons_use_time FROM (SELECT c.*,d.customer_level,mobile,realname FROM (SELECT a.*, b.name FROM (SELECT id,level_id,state,total_price,total_point,(total_price-realpay_amount)AS coupons_amount,realpay_amount,customer_user_id,orderNum,DATE_FORMAT(create_time,'%Y-%m-%d %H:%i:%S') AS create_time,merchant_id,order_id,trade_no FROM tb_order_info WHERE id=1)AS a LEFT JOIN (SELECT id,name FROM tb_u_level)AS b ON a.level_id=b.id)AS c LEFT JOIN (SELECT e.*,f.customer_level FROM (SELECT id,mobile,realname,level_id FROM tb_u_customer_user)AS e LEFT JOIN (SELECT id,CONCAT(prov_name,'-',city_name,'-',district_name,'-',branch_name)AS customer_level FROM tb_u_level)AS f ON e.level_id=f.id)AS d ON c.customer_user_id=d.id)AS g LEFT JOIN (SELECT GROUP_CONCAT(coupons_id)AS coupons_id,GROUP_CONCAT(status)AS coupons_status,GROUP_CONCAT(DATE_FORMAT(use_time,'%Y-%m-%d %H:%i:%S'))AS coupons_use_time,order_id FROM tb_goods_coupons GROUP BY order_id)AS h ON g.id=h.order_id)AS l LEFT JOIN (SELECT GROUP_CONCAT(k.name)AS goods_name,GROUP_CONCAT(k.count)AS goods_count,GROUP_CONCAT(k.price)AS goods_price,order_id FROM (SELECT i.price,count,order_id,j.name FROM (SELECT * FROM tb_order_goods)AS i LEFT JOIN (SELECT * FROM tb_goods)AS j ON i.goods_id=j.id)AS k GROUP BY order_id)AS m ON l.id=m.order_id)AS p LEFT JOIN (SELECT n.*,o.account,level_name FROM (SELECT id,name AS merchant_name,wyfMerchantID,level_id FROM tb_merchant)AS n LEFT JOIN (SELECT id,name AS level_name,account FROM tb_u_level)AS o ON n.level_id=o.id)AS q ON p.merchant_id=q.id;
        #     '''
        #     cursor.execute(sql)
        # ziduan = ['id', '平台订单号', '订单号', '支付流水号', '下单时间', '商品名称', '单价', '数量', '总金额(元)', '商家信息', '微邮付商户号', '所属机构', '所属机构号', '购买网点', '订单状态', '邮米抵扣', '优惠券抵扣(元)', '实付金额(元)', '券码', '券码状态', '券码核销时间', '购买用户手机号', '用户真实姓名', '用户归属', '是否微邮付商户', '微邮付商户号', '微邮付商户简称', '微邮付商户归属']
        # cols = ['id', 'order_id', 'orderNum', 'trade_no', 'create_time', 'goods_name', 'goods_price', 'goods_count', 'total_price', 'merchant_name', 'wyfMerchantID', 'level_name', 'account', 'name', 'state', 'total_point', 'coupons_amount', 'realpay_amount', 'coupons_id', 'coupons_status', 'coupons_use_time', 'mobile', 'realname', 'customer_level', 'is_merchant', 'business_no', 'short_name', 'merchant_level']
        try:
            sql = f'''
            SELECT t.*,u.address_mobile,receiver,province,city,district,place FROM (SELECT r.*,s.vice_mobile,vice_realname FROM (SELECT p.*,q.merhant_acount,merchant_city_name,merhant_district_name,merchant_branch_name,merchant_name,wyfMerchantID FROM (SELECT l.*,m.goods_name,goods_count,goods_price FROM (SELECT g.*,h.coupons_id,coupons_status,coupons_use_time FROM (SELECT c.*,d.customer_level,mobile,realname FROM (SELECT a.*, b.order_city_name,order_district_name,order_branch_name,order_account FROM (SELECT id,level_id,state,total_price,total_point,(total_price-realpay_amount)AS coupons_amount,realpay_amount,customer_user_id,orderNum,DATE_FORMAT(create_time,'%Y-%m-%d %H:%i:%S') AS create_time,DATE_FORMAT(payment_time,'%Y-%m-%d %H:%i:%S') AS payment_time,merchant_id,order_id,trade_no,customeruservice_id FROM tb_order_info {condition})AS a LEFT JOIN (SELECT id,city_name AS order_city_name,district_name AS order_district_name,branch_name AS order_branch_name,account AS order_account FROM tb_u_level)AS b ON a.level_id=b.id)AS c LEFT JOIN (SELECT e.*,f.customer_level FROM (SELECT id,mobile,realname,level_id FROM tb_u_customer_user)AS e LEFT JOIN (SELECT id,CONCAT(prov_name,'-',city_name,'-',district_name,'-',branch_name)AS customer_level FROM tb_u_level)AS f ON e.level_id=f.id)AS d ON c.customer_user_id=d.id)AS g LEFT JOIN (SELECT GROUP_CONCAT(coupons_id)AS coupons_id,GROUP_CONCAT(status)AS coupons_status,GROUP_CONCAT(DATE_FORMAT(use_time,'%Y-%m-%d %H:%i:%S'))AS coupons_use_time,order_id FROM tb_goods_coupons WHERE order_id IN (SELECT id FROM tb_order_info {condition}) GROUP BY order_id)AS h ON g.id=h.order_id)AS l LEFT JOIN (SELECT GROUP_CONCAT(k.name)AS goods_name,GROUP_CONCAT(k.count)AS goods_count,GROUP_CONCAT(k.price)AS goods_price,order_id FROM (SELECT i.price,count,order_id,j.name FROM (SELECT * FROM tb_order_goods WHERE order_id IN (SELECT id FROM tb_order_info {condition}))AS i LEFT JOIN (SELECT * FROM tb_goods)AS j ON i.goods_id=j.id)AS k GROUP BY order_id)AS m ON l.id=m.order_id)AS p LEFT JOIN (SELECT n.*,o.merhant_acount,merchant_city_name,merhant_district_name,merchant_branch_name FROM (SELECT id,name AS merchant_name,wyfMerchantID,level_id FROM tb_merchant)AS n LEFT JOIN (SELECT id,city_name AS merchant_city_name,district_name AS merhant_district_name,branch_name AS merchant_branch_name,account AS merhant_acount FROM tb_u_level)AS o ON n.level_id=o.id)AS q ON p.merchant_id=q.id)AS r LEFT JOIN (SELECT id,mobile AS vice_mobile,realname AS vice_realname FROM tb_u_customer_user_vice WHERE id IN (SELECT customeruservice_id FROM tb_order_info {condition}))AS s ON r.customeruservice_id=s.id)AS t LEFT JOIN (SELECT receiver,province,city,district,place,mobile AS address_mobile,order_id FROM tb_order_address WHERE order_id IN (SELECT id FROM tb_order_info {condition}))AS u ON t.id=u.order_id;
            '''
            cursor.execute(sql)
        except Exception as e:
            sql = f'''
            SELECT p.*,q.account,level_name,merchant_name,wyfMerchantID FROM (SELECT l.*,m.goods_name,goods_count,goods_price FROM (SELECT g.*,h.coupons_id,coupons_status,coupons_use_time FROM (SELECT c.*,d.customer_level,mobile,realname FROM (SELECT a.*, b.name FROM (SELECT id,level_id,state,total_price,total_point,(total_price-realpay_amount)AS coupons_amount,realpay_amount,customer_user_id,orderNum,DATE_FORMAT(create_time,'%Y-%m-%d %H:%i:%S') AS create_time,merchant_id,order_id,trade_no FROM tb_order_info WHERE id=1)AS a LEFT JOIN (SELECT id,name FROM tb_u_level)AS b ON a.level_id=b.id)AS c LEFT JOIN (SELECT e.*,f.customer_level FROM (SELECT id,mobile,realname,level_id FROM tb_u_customer_user)AS e LEFT JOIN (SELECT id,CONCAT(prov_name,'-',city_name,'-',district_name,'-',branch_name)AS customer_level FROM tb_u_level)AS f ON e.level_id=f.id)AS d ON c.customer_user_id=d.id)AS g LEFT JOIN (SELECT GROUP_CONCAT(coupons_id)AS coupons_id,GROUP_CONCAT(status)AS coupons_status,GROUP_CONCAT(DATE_FORMAT(use_time,'%Y-%m-%d %H:%i:%S'))AS coupons_use_time,order_id FROM tb_goods_coupons GROUP BY order_id)AS h ON g.id=h.order_id)AS l LEFT JOIN (SELECT GROUP_CONCAT(k.name)AS goods_name,GROUP_CONCAT(k.count)AS goods_count,GROUP_CONCAT(k.price)AS goods_price,order_id FROM (SELECT i.price,count,order_id,j.name FROM (SELECT * FROM tb_order_goods)AS i LEFT JOIN (SELECT * FROM tb_goods)AS j ON i.goods_id=j.id)AS k GROUP BY order_id)AS m ON l.id=m.order_id)AS p LEFT JOIN (SELECT n.*,o.account,level_name FROM (SELECT id,name AS merchant_name,wyfMerchantID,level_id FROM tb_merchant)AS n LEFT JOIN (SELECT id,name AS level_name,account FROM tb_u_level)AS o ON n.level_id=o.id)AS q ON p.merchant_id=q.id;
            '''
            cursor.execute(sql)
        ziduan = ['id', '平台订单号', '订单号', '支付流水号', '下单时间', '商品名称', '单价', '数量', '总金额(元)', '商家信息', '微邮付商户号', '商家所属市公司', '商家所属区公司', '商家所属网点', '商家所属机构号', '购买市公司', '购买区公司', '购买网点', '购买机构号', '订单状态', '付款时间', '邮米抵扣', '优惠券抵扣(元)', '实付金额(元)', '券码', '券码状态', '券码核销时间', '购买用户手机号', '用户真实姓名', '用户归属', '收货人', '收货人手机号', '收货地址']
        cols = ['id', 'order_id', 'orderNum', 'trade_no', 'create_time', 'goods_name', 'goods_price', 'goods_count', 'total_price', 'merchant_name', 'wyfMerchantID', 'merchant_city_name', 'merhant_district_name', 'merchant_branch_name', 'merhant_acount', 'order_city_name', 'order_district_name', 'order_branch_name', 'order_account', 'state', 'payment_time', 'total_point', 'coupons_amount', 'realpay_amount', 'coupons_id', 'coupons_status', 'coupons_use_time', 'mobile', 'realname', 'customer_level', 'receiver', 'address_mobile', 'place']
        response = StreamingHttpResponse(self.get_orderinfo_fromat(cols, cursor, conn, ziduan))
        response['Content-Type'] = 'application/octet-stream; charset=gbk'
        response['Content-Disposition'] = "attachment; filename*=utf-8''{}".format(escape_uri_path('订单列表.csv'))
        return response

    def get_orderinfo_fromat(self, cols, cursor, conn, ziduan):
        tmp_str = ""
        # 返回文件的每一列列名
        for col in ziduan:
            tmp_str += '"%s",' % (col)
        yield tmp_str.strip(",") + "\n"
        STATUS_ENUM = {
            0: '待付款',
            1: '待付款',
            2: '待核销',
            3: '已核销',
            4: '订单过期',
            5: '售后中',
            6: '已发货',
            7: '已预约',
            8: '已退款',
            9: '发货中',
            10: '退款中',
            11: '订单异常',
            12: '已付款',
            13: '已取消',
            14: '已完成',
            15: '待成团'
        }
        COUPONS_STATUS_ENUM = {
            "0": '未激活',
            "1": '待核销',
            "2": '已核销',
            "3": '已过期',
            "4": '已撤销'
        }
        check_order = []
        while True:
            tmp_str = ""
            row = cursor.fetchone()
            if row is None:
                cursor.close()
                conn.close()
                break
            if row['order_id'] not in check_order:
                check_order.append(row['order_id'])
                for col in cols:
                    if col == 'state':
                        tmp_str += '"%s",' % (STATUS_ENUM[row[col]])
                    elif col == 'is_merchant':
                        if row['business_no']:
                            tmp_str += '"%s",' % '是'
                        else:
                            tmp_str += '"%s",' % '否'
                    elif col == 'coupons_status':
                        coupons_status_str = ''
                        if row[col]:
                            coupons_status_list = row[col].split(',')
                            for coupons_status in coupons_status_list:
                                coupons_status_str += COUPONS_STATUS_ENUM[coupons_status]
                                coupons_status_str += ','
                        tmp_str += '"%s",' % (coupons_status_str)
                    elif col in ['mobile', 'realname']:
                        if row['customeruservice_id']:
                            tmp_str += '"%s",' % (str(row[f'vice_{col}']).encode('GBK', 'ignore').decode('gbk') if row[f'vice_{col}'] else '')
                        else:
                            tmp_str += '"%s",' % (str(row[f'{col}']).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
                    elif col == 'place':
                        tmp_str += '"%s",' % (str(f'{row["province"]}-{row["city"]}-{row["district"]}-{row[col]}').encode('GBK', 'ignore').decode('gbk') if row[col] else '')
                    elif col in ['orderNum', 'trade_no', 'order_id']:
                        tmp_str += '"\'%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
                    elif col == 'coupons_id':
                        if row['state'] == 2:
                            tmp_str += '"\'%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
                        else:
                            tmp_str += '"\'%s",' % ('')
                    elif col in ['total_price', 'total_point', 'coupons_amount', 'realpay_amount']:
                        tmp_str += '"%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else 0)
                    else:
                        tmp_str += '"%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
                yield tmp_str.strip(',') + "\n"

    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        if instance.state != 1:
            return Response({'error': '订单状态错误'}, status=status.HTTP_400_BAD_REQUEST)
        ordergoods_set = instance.ordergoods_set.all()
        for ordergoods in ordergoods_set:
            goods = ordergoods.goods
            launched_goods = ordergoods.launched_goods
            count = ordergoods.count
            origin_sales = goods.sales
            new_sales = origin_sales - count
            goods.sales = new_sales
            goods.save()
            if launched_goods:
                launched_origin_stock = launched_goods.stock
                launched_origin_sales = launched_goods.sales
                launched_new_stock = launched_origin_stock + count
                launched_new_sales = launched_origin_sales - count
                launched_goods.stock = launched_new_stock
                launched_goods.sales = launched_new_sales
                launched_goods.save()
            else:
                origin_stock = goods.stock
                new_stock = origin_stock + count
                goods.stock = new_stock
                goods.save()
        instance.state = 13
        instance.cancel_time = datetime.datetime.now()
        instance.total_point = 0
        instance.save()
        alidiscounponinfo_set = instance.alidiscountcouponinfo_set.all().filter(status=8).update(status=1, order_id=None)
        try:
            user = instance.customer_user
            pointrecord_set = instance.pointrecord_set.all()
            for pointrecord in pointrecord_set:
                activity_data = pointrecord.activity_data
                activity_data.remain_point += pointrecord.point
                activity_data.state = 3
                activity_data.save()
                user.point += pointrecord.point
                user.save()
                in_pointrecord_data = {}
                in_pointrecord_data['customer_user_id'] = user.id
                in_pointrecord_data['create_time'] = datetime.datetime.now()
                in_pointrecord_data['operate_type'] = 1
                in_pointrecord_data['business_type'] = 4
                in_pointrecord_data['point'] = pointrecord.point
                in_pointrecord_data['point_balance'] = user.point
                in_pointrecord_data['remain_point'] = activity_data.remain_point
                in_pointrecord_data['activity_data_id'] = activity_data.id
                in_pointrecord_data['order_id'] = instance.id
                PointRecord.objects.create(**in_pointrecord_data)
        except:
            pass
        return Response({'success': '取消订单成功'}, status=status.HTTP_200_OK)

    def update_fund_trans(self, request, *args, **kwargs):
        fund_id = self.request.data.get('fund_id', None)
        identity = self.request.data.get('identity', None)
        name = self.request.data.get('name', None)
        if not all([fund_id, identity, name]):
            return Response({'error': '缺少必传参数'}, status=status.HTTP_400_BAD_REQUEST)
        try:
            orderfundtrans = OrderFundTrans.objects.get(id=fund_id)
        except:
            return Response({'error': '无效转账id'}, status=status.HTTP_400_BAD_REQUEST)
        if orderfundtrans.status == 2:
            return Response({'error': '已转账成功,不可更改转账信息'}, status=status.HTTP_400_BAD_REQUEST)
        if orderfundtrans.status == 3:
            return Response({'error': '转账处理中,不可更改转账信息'}, status=status.HTTP_400_BAD_REQUEST)
        origin_identity = orderfundtrans.identity
        origin_name = orderfundtrans.name
        if origin_identity == identity and origin_name == name:
            return Response({'error': '转账信息无更正'}, status=status.HTTP_400_BAD_REQUEST)
        orderfundtrans.identity = identity
        orderfundtrans.name = name
        orderfundtrans.sub_msg = None
        if orderfundtrans.status == 4:
            origin_out_biz_no = orderfundtrans.out_biz_no
            new_out_biz_no = f'{int(origin_out_biz_no[:1])+1}{origin_out_biz_no[1:]}'
            orderfundtrans.out_biz_no = new_out_biz_no
        orderfundtrans.save()
        order = orderfundtrans.order
        if order.state == 12:
            alipay_obj = C_AlipayOpen()
            trans_amount = str(orderfundtrans.exchange_amount)
            order_title = orderfundtrans.order_title
            out_biz_no = orderfundtrans.out_biz_no
            identity = orderfundtrans.identity
            if orderfundtrans.identity_type == 1:
                result = json.loads(alipay_obj.transunitransfer_user_id(identity, out_biz_no, trans_amount, order_title))
            else:
                name = orderfundtrans.name
                result = json.loads(alipay_obj.transunitransfer_login_id(identity, name, out_biz_no, trans_amount, order_title))
            if result['code'] != '10000':
                orderfundtrans.sub_msg = result['sub_msg']
                orderfundtrans.status = 4
                orderfundtrans.save()
                # try:
                #     ali_fundtrans_template(order.id, str(trans_amount), result['sub_msg'])
                # except:
                #     pass
                return Response({'success': '修改转账信息成功,转账信息仍然有误,转账失败'}, status=status.HTTP_200_OK)
            else:
                orderfundtrans.ali_order_id = result['order_id']
                orderfundtrans.pay_fund_order_id = result['pay_fund_order_id']
                orderfundtrans.trans_date = result['trans_date']
                orderfundtrans.status = 2
                orderfundtrans.save()
                return Response({'success': '修改转账信息成功,并已转账成功'}, status=status.HTTP_200_OK)
        else:
            return Response({'success': '修改转账信息成功'}, status=status.HTTP_200_OK)


class AliDiscountCouponInfoModelViewSet(ModelViewSet):

    pagination_class = MyPage
    filter_class = AliDiscountCouponInfoFilter
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)
    search_fields = ('mobile', )

    def get_queryset(self):
        user = self.request.iser
        level = user.level
        level_id = self.request.query_params.get('level', None)
        alidiscountcoupon_level_id = self.request.query_params.get('alidiscountcoupon_level_id', None)
        activity_id = self.request.query_params.get('activity_id', None)
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        try:
            if '_mutable' in self.request.data.__dict__:
                self.request.data.__dict__['_mutable'] = True
        except:
            pass
        if alidiscountcoupon_level_id:
            try:
                couponlevel = AliDiscountCouponLevel.objects.get(id=alidiscountcoupon_level_id)
                self.request.data['acitivty_info'] = AliDiscountCouponLevelListModelSerializer(couponlevel).data
            except:
                self.request.data['acitivty_info'] = {}
        if level.level == 0:
            queryset = AliDiscountCouponInfo.objects.all().order_by('-id')
        elif level.level == 1:
            queryset = AliDiscountCouponInfo.objects.filter(level__prov_id=level.id).order_by('-id')
        elif level.level == 2:
            queryset = AliDiscountCouponInfo.objects.filter(level__city_id=level.id).order_by('-id')
        elif level.level == 3:
            queryset = AliDiscountCouponInfo.objects.filter(level__district_id=level.id).order_by('-id')
        else:
            queryset = AliDiscountCouponInfo.objects.filter(level__branch_id=level.id).order_by('-id')
        if not alidiscountcoupon_level_id and not activity_id:
            city_list = list(AliDiscountCoupon.objects.filter(alidiscountcouponlevel__level_id=level.id).values_list('id', flat=True))
            queryset = queryset.filter(alidiscountcoupon_id__in=city_list)
        return queryset

    def get_serializer_class(self):
        if self.action == 'list':
            return AliDiscountCouponInfoListModelSerializer
        else:
            return AliDiscountCouponInfoRetrieveModelSerializer

    def export_discountinfo(self, request):
        user = self.request.iser
        activity_id = self.request.query_params.get('activity_id', None)
        alidiscountcoupon_level_id = self.request.query_params.get('alidiscountcoupon_level_id', None)
        level_id = self.request.query_params.get('level_id', None)
        status = self.request.query_params.get('status', None)
        search = self.request.query_params.get('search', None)
        level = user.level
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        if level.level == 0:
            condition = 'WHERE id != 1'
        elif level.level == 1:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE prov_id={level.id})'
        elif level.level == 2:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE city_id={level.id})'
        elif level.level == 3:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE district_id={level.id})'
        else:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE branch_id={level.id})'
        if search:
            condition = condition + f' AND mobile LIKE "%{search}%"'
        if activity_id:
            condition = condition + f' AND alidiscountcoupon_id in ({activity_id})'
        if status:
            condition = condition + f' AND status in ({status})'
        if alidiscountcoupon_level_id:
            condition = condition + f' AND alidiscountcoupon_level_id={alidiscountcoupon_level_id}'
        conn = pymysql.connect(host=settings.DATABASES['default']['HOST'],
                               port=settings.DATABASES['default']['PORT'],
                               database=settings.DATABASES['default']['NAME'],
                               user=settings.DATABASES['default']['USER'],
                               password=settings.DATABASES['default']['PASSWORD'])
        cursor = conn.cursor(cursor=pymysql.cursors.SSDictCursor)
        try:
            sql = f'''
            SELECT m.*,n.vice_idcode,vice_realname FROM (SELECT k.*,l.orderNum,total_count,total_price,realpay_amount,create_time,order_id FROM (SELECT i.*,j.trade_no FROM (SELECT g.*,h.activity_name FROM (SELECT e.*,f.account,name FROM (SELECT c.*,d.nickname FROM (SELECT a.*,b.idcode,realname FROM (SELECT id,mobile,status,customer_user_id,companyuser_id,level_id,DATE_FORMAT(gmt_distributed,'%Y-%m-%d %H:%i:%S')AS gmt_distributed,DATE_FORMAT(gmt_undo,'%Y-%m-%d %H:%i:%S')AS gmt_undo,alidiscountcoupon_id,customeruservice_id FROM tb_ali_discount_coupon_info {condition})AS a LEFT JOIN (SELECT id,realname,idcode FROM tb_u_customer_user)AS b ON a.customer_user_id=b.id)AS c LEFT JOIN (SELECT id,nickname FROM tb_u_user)AS d ON c.companyuser_id=d.id)AS e LEFT JOIN (SELECT id,name,account FROM tb_u_level)AS f ON e.level_id=f.id)AS g LEFT JOIN (SELECT id,activity_name FROM tb_ali_discount_coupon)AS h on g.alidiscountcoupon_id=h.id)AS i LEFT JOIN (SELECT trade_no,voucherinfo_id FROM tb_ali_discount_coupon_bill_details)AS j ON i.id=j.voucherinfo_id)AS k LEFT JOIN (SELECT orderNum,total_count,total_price,create_time,realpay_amount,id AS order_id FROM tb_order_info WHERE order_species=2)AS l ON k.trade_no=l.orderNum)AS m LEFT JOIN (SELECT id,realname AS vice_realname,idcode AS vice_idcode FROM tb_u_customer_user_vice)AS n ON m.customeruservice_id=n.id;
            '''
            cursor.execute(sql)
        except:
            sql = f'''
            SELECT r.*,s.goods_name FROM (SELECT m.*,n.coupons_id FROM (SELECT k.*,l.orderNum,total_count,total_price,realpay_amount,create_time,order_id FROM (SELECT i.*,j.trade_no FROM (SELECT g.*,h.activity_name FROM (SELECT e.*,f.account,name FROM (SELECT c.*,d.nickname FROM (SELECT a.*,b.idcode,realname FROM (SELECT id,mobile,status,customer_user_id,companyuser_id,level_id,DATE_FORMAT(gmt_distributed,'%Y-%m-%d %H:%i:%S')AS gmt_distributed,DATE_FORMAT(gmt_undo,'%Y-%m-%d %H:%i:%S')AS gmt_undo,alidiscountcoupon_id FROM tb_ali_discount_coupon_info)AS a LEFT JOIN (SELECT id,realname,idcode FROM tb_u_customer_user)AS b ON a.customer_user_id=b.id)AS c LEFT JOIN (SELECT id,nickname FROM tb_u_user)AS d ON c.companyuser_id=d.id)AS e LEFT JOIN (SELECT id,name,account FROM tb_u_level)AS f ON e.level_id=f.id)AS g LEFT JOIN (SELECT id,activity_name FROM tb_ali_discount_coupon)AS h on g.alidiscountcoupon_id=h.id)AS i LEFT JOIN (SELECT trade_no,voucherinfo_id FROM tb_ali_discount_coupon_bill_details)AS j ON i.id=j.voucherinfo_id)AS k LEFT JOIN (SELECT orderNum,total_count,total_price,create_time,realpay_amount,id AS order_id FROM tb_order_info)AS l ON k.trade_no=l.orderNum)AS m LEFT JOIN (SELECT GROUP_CONCAT(coupons_id)AS coupons_id,order_id FROM tb_goods_coupons GROUP BY order_id)AS n ON m.order_id=n.order_id)AS r LEFT JOIN (SELECT GROUP_CONCAT(q.name)AS goods_name,q.order_id FROM (SELECT o.*,p.name FROM (SELECT order_id,goods_id FROM tb_order_goods)AS o LEFT JOIN (SELECT id,name FROM tb_goods)AS p ON o.goods_id=p.id)AS q GROUP BY q.order_id)AS s ON r.order_id=s.order_id;
            '''
            cursor.execute(sql)
        ziduan = ['优惠券ID', '领取手机号', '领取状态', '领取人姓名', '领取人证件号码', '派发人姓名', '派发人所属网点', '网点机构号',
                  '派发时间', '撤销时间', '活动名称', '数量', '订单金额', '实际支付金额', '下单时间', '订单号']
        cols = ['id', 'mobile', 'status', 'realname', 'idcode', 'nickname', 'name', 'account', 'gmt_distributed', 'gmt_undo', 'activity_name',
                'total_count', 'total_price', 'realpay_amount', 'create_time', 'trade_no']
        response = StreamingHttpResponse(self.get_discountinfo_fromat(cols, cursor, conn, ziduan))
        response['Content-Type'] = 'application/octet-stream; charset=gbk'
        response['Content-Disposition'] = "attachment; filename*=utf-8''{}".format(escape_uri_path('优惠券派发核销数据.csv'))
        return response

    def get_discountinfo_fromat(self, cols, cursor, conn, ziduan):
        tmp_str = ""
        # 返回文件的每一列列名
        for col in ziduan:
            tmp_str += '"%s",' % (col)
        yield tmp_str.strip(",") + "\n"
        STATUS_ENUM = {
            0: '待领取',
            1: '待核销',
            2: '不可用',
            3: '删除状态',
            4: '发送中',
            5: '已转增',
            6: '未领取',
            7: '已核销',
            8: '使用中',
            9: '已退款',
            10: '退款中',
            11: '未激活',
            12: '已过期',
            13: '已撤销',
            14: '领取失败'
        }
        while True:
            tmp_str = ""
            row = cursor.fetchone()
            if row is None:
                cursor.close()
                conn.close()
                break
            for col in cols:
                if col == 'status':
                    tmp_str += '"%s",' % (STATUS_ENUM[row[col]])
                elif col in ['realname']:
                    if row['customeruservice_id']:
                        tmp_str += '"%s",' % (str(row['vice_realname']).encode('GBK', 'ignore').decode('gbk') if row['vice_realname'] else '')
                    else:
                        tmp_str += '"%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
                elif col in ['idcode']:
                    if row['customeruservice_id']:
                        tmp_str += '"\'%s",' % (str(row['vice_idcode']).encode('GBK', 'ignore').decode('gbk') if row['vice_idcode'] else '')
                    else:
                        tmp_str += '"\'%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
                elif col in ['trade_no', 'coupons_id']:
                    tmp_str += '"\'%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
                else:
                    tmp_str += '"%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
            yield tmp_str.strip(',') + "\n"


class AliDiscountCouponModelViewSet(ModelViewSet):

    pagination_class = MyPage
    search_fields = ('activity_name', 'template_id')
    filter_class = AliDiscountCouponFilter
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)

    def get_queryset(self):
        today = datetime.datetime.now()
        user = self.request.iser
        level = user.level
        level_id = self.request.query_params.get('level', None)
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        queryset = AliDiscountCoupon.objects.filter(alidiscountcouponlevel__level_id=level.id)
        return queryset.filter(publish_end_time__gte=today).exclude(coupon_status=3).order_by('-id')

    def get_serializer_context(self):
        user = self.request.iser
        return {'user': user}

    def get_serializer_class(self):
        if self.action == 'list':
            return AliDiscountCouponListModelSerializer
        else:
            return AliDiscountCouponRetrieveModelSerializer

    def update(self, request, *args, **kwargs):
        instance = self.get_object()
        coupon_way = self.request.data.get('coupon_way', None)
        publish_start_time = self.request.data.get('publish_start_time', None)
        publish_end_time = self.request.data.get('publish_end_time', None)
        is_need_auth = self.request.data.get('is_need_auth', None)
        is_white = self.request.data.get('is_white', None)
        is_union = self.request.data.get('is_union', None)
        available_merchants = self.request.data.get('available_merchants', None)
        activity_description = self.request.data.get('activity_description', None)
        max_number = self.request.data.get('max_number', None)
        distributed_limit_by_time = self.request.data.get('distributed_limit_by_time', None)
        distributed_limit_by_time_rules = self.request.data.get('distributed_limit_by_time_rules', [])
        with transaction.atomic():
            # 创建事务保存点
            save_id = transaction.savepoint()

            # 暴力回滚
            try:
                # if str(coupon_way) in ['1', '2', '3']:
                #     instance.coupon_way = coupon_way
                if publish_start_time and publish_end_time:
                    try:
                        publish_start_time = datetime.datetime.strptime(publish_start_time, "%Y-%m-%d %H:%M:%S")
                        publish_end_time = datetime.datetime.strptime(publish_end_time, "%Y-%m-%d %H:%M:%S")
                    except:
                        return Response({'error': '活动时间区间参数有误!'}, status=status.HTTP_400_BAD_REQUEST)
                    if publish_start_time >= publish_end_time:
                        return Response({'error': '活动开始时间须大于结束时间!'}, status=status.HTTP_400_BAD_REQUEST)
                    if datetime.datetime.now() >= publish_end_time:
                        return Response({'error': '活动结束时间须大于当前时间!'}, status=status.HTTP_400_BAD_REQUEST)
                    instance.publish_start_time = publish_start_time
                    instance.publish_end_time = publish_end_time
                    if instance.coupon_status == 2:
                        instance.coupon_status = 3
                if str(is_need_auth) in ['0', '1']:
                    instance.is_need_auth = is_need_auth
                if str(is_white) in ['0', '1']:
                    instance.is_white = is_white
                if str(is_union) in ['0', '1']:
                    instance.is_union = is_union
                if available_merchants:
                    instance.available_merchants = available_merchants
                if activity_description:
                    instance.activity_description = activity_description
                if max_number:
                    try:
                        max_number = int(max_number)
                    except:
                        return Response({'error': '活动最大派发数参数有误!'}, status=status.HTTP_400_BAD_REQUEST)
                    old_max_number = instance.max_number
                    instance.max_number = max_number
                    instance.remain_number = instance.remain_number + max_number - old_max_number
                if str(distributed_limit_by_time) in ['1', '2']:
                    channelcommonvoucher = instance.alidiscountcouponchannelcommonvoucher
                    if str(distributed_limit_by_time) == '1' and channelcommonvoucher.distributed_limit_by_time == 2:
                        if not distributed_limit_by_time_rules:
                            return Response({'error': '请上传固定派发时间规则!'}, status=status.HTTP_400_BAD_REQUEST)
                    channelcommonvoucher.distributed_limit_by_time = distributed_limit_by_time
                    channelcommonvoucher.save()
                    alidiscountcoupondistributedlimit_set = channelcommonvoucher.alidiscountcoupondistributedlimit_set.all().delete()
                    for rule in distributed_limit_by_time_rules:
                        start_enable_time = rule['start_enable_time']
                        end_enable_time = rule['end_enable_time']
                        weeks = rule['weeks']
                        try:
                            start_enable_time = datetime.datetime.strptime(f'1970-01-01 {start_enable_time}', "%Y-%m-%d %H:%M:%S")
                            end_enable_time = datetime.datetime.strptime(f'1970-01-01 {end_enable_time}', "%Y-%m-%d %H:%M:%S")
                        except:
                            transaction.savepoint_rollback(save_id)
                            return Response({'error': '派发时间区间参数有误!'}, status=status.HTTP_400_BAD_REQUEST)
                        if start_enable_time >= end_enable_time:
                            transaction.savepoint_rollback(save_id)
                            return Response({'error': '派发时间区间参数有误!'}, status=status.HTTP_400_BAD_REQUEST)
                        AliDiscountCouponDistributedLimit.objects.create(
                            ali_discount_coupon_common_voucher_id=channelcommonvoucher.id,
                            start_enable_time=start_enable_time,
                            end_enable_time=end_enable_time,
                            weeks=weeks
                        )
                instance.save()
                transaction.savepoint_commit(save_id)
                return Response({'success': '修改成功!'}, status=status.HTTP_200_OK)
            except Exception as e:
                logger.error(e)
                # 事务回滚
                transaction.savepoint_rollback(save_id)
                return Response({'error': '修改失败,请联系管理员'}, status=status.HTTP_400_BAD_REQUEST)

    def update_white_table(self, request):
        activity_id = self.request.data.get('activity_id', None)
        mobile_array = self.request.data.get('mobile_array', None)
        try:
            instance = self.get_queryset().get(id=activity_id)
        except:
            return Response({'error': '无效活动id'}, status=status.HTTP_400_BAD_REQUEST)
        with transaction.atomic():
            # 创建事务保存点
            save_id = transaction.savepoint()

            # 暴力回滚
            try:
                alidiscountcouponwhitetable_set = instance.alidiscountcouponwhitetable_set.all().delete()
                for mobile in mobile_array:
                    if not re.match(r'^1[3-9]\d{9}$', mobile):
                        transaction.savepoint_rollback(save_id)
                        return Response({'error': f'{mobile}非手机号格式'}, status=status.HTTP_400_BAD_REQUEST)
                    AliDiscountCouponWhiteTable.objects.create(alidiscountcoupon_id=activity_id, mobile=mobile)

                transaction.savepoint_commit(save_id)
                return Response({'success': '修改成功'}, status=status.HTTP_200_OK)
            except Exception as e:
                logger.error(e)
                # 事务回滚
                transaction.savepoint_rollback(save_id)
                return Response({'error': '修改失败,请联系管理员'}, status=status.HTTP_400_BAD_REQUEST)

    def partial_update(self, request, *args, **kwargs):
        instance = self.get_object()
        coupon_status = self.request.data.get('coupon_status', None)
        if instance.coupon_status == 2:
            return Response({'error': '活动已结束, 不可操作'}, status=status.HTTP_400_BAD_REQUEST)
        if str(coupon_status) == '1':
            alidiscountcoupon = AliDiscountCouponLevel.objects.filter(activity_id=instance.id)
            if not alidiscountcoupon and instance.coupon_way in [3, 2]:
                alidiscountcoupon_data = {}
                alidiscountcoupon_data['level_id'] = instance.level_id
                alidiscountcoupon_data['activity_id'] = instance.id
                alidiscountcoupon_data['max_number'] = instance.max_number
                alidiscountcoupon_data['remain_number'] = instance.max_number
                alidiscountcoupon_data['p_max_number'] = instance.max_number
                alidiscountcoupon_data['p_remain_number'] = instance.max_number
                identify = random_str(randomlength=64)
                common_url = f'https://api.sutpay.com/customer/coupon/?identify={identify}'
                common_qrcode = f'youhuiquanyi/coupon/{identify}.png'
                common_qrcode_url = make_qrcode2(identify, common_url, common_qrcode)
                alidiscountcoupon_data['common_url'] = common_url
                alidiscountcoupon_data['common_qrcode'] = common_qrcode
                alidiscountcoupon_data['identify'] = identify
                AliDiscountCouponLevel.objects.get_or_create(activity_id=instance.id, level_id=instance.level_id, defaults=alidiscountcoupon_data)
            instance.coupon_status = 1
            instance.save()
            return Response({'success': '开启活动成功'}, status=status.HTTP_200_OK)
        elif str(coupon_status) == '2':
            instance.coupon_status = 4
            instance.save()
            return Response({'success': '暂停活动成功'}, status=status.HTTP_200_OK)
        else:
            return Response({'error': '无效活动状态'}, status=status.HTTP_400_BAD_REQUEST)

    def white_table(self, request):
        activity_id = self.request.query_params.get('activity_id', None)
        try:
            instance = self.get_queryset().get(id=activity_id)
        except:
            return Response({'error': '无效活动id'}, status=status.HTTP_400_BAD_REQUEST)
        alidiscountcouponwhitetable_set = instance.alidiscountcouponwhitetable_set.all().values_list('mobile', flat=True)
        return Response({'data': list(alidiscountcouponwhitetable_set)}, status=status.HTTP_200_OK)

    def export_activity_merchant(self, request):
        activity_id = self.request.query_params.get('activity_id', None)
        try:
            instance = self.get_queryset().get(id=activity_id)
        except:
            return Response({'error': '无效活动id'}, status=status.HTTP_400_BAD_REQUEST)
        conn = pymysql.connect(host=settings.DATABASES['default']['HOST'],
                               port=settings.DATABASES['default']['PORT'],
                               database=settings.DATABASES['default']['NAME'],
                               user=settings.DATABASES['default']['USER'],
                               password=settings.DATABASES['default']['PASSWORD'])
        cursor = conn.cursor(cursor=pymysql.cursors.SSDictCursor)
        sql = f'''
        SELECT short_name,wyfMerchantID,name,id FROM tb_merchant WHERE id IN (SELECT merchant_id FROM tb_ali_discount_coupon_merchant WHERE alidiscountcoupon_id={activity_id});
        '''
        cursor.execute(sql)
        ziduan = ['id', '活动名称', '可用商户全称', '可用商户简称', '微邮付商户号']
        cols = ['id', 'acitivity_name' ,'name', 'short_name', 'wyfMerchantID']
        response = StreamingHttpResponse(self.get_activity_merchant_fromat(cols, cursor, conn, ziduan, instance.activity_name))
        response['Content-Type'] = 'application/octet-stream; charset=gbk'
        response['Content-Disposition'] = "attachment; filename*=utf-8''{}".format(escape_uri_path('订单列表.csv'))
        return response

    def get_activity_merchant_fromat(self, cols, cursor, conn, ziduan, acitivity_name):
        tmp_str = ""
        # 返回文件的每一列列名
        for col in ziduan:
            tmp_str += '"%s",' % (col)
        yield tmp_str.strip(",") + "\n"
        while True:
            tmp_str = ""
            row = cursor.fetchone()
            if row is None:
                cursor.close()
                conn.close()
                break
            for col in cols:
                if col == 'acitivity_name':
                    tmp_str += '"%s",' % acitivity_name
                else:
                    tmp_str += '"%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
            yield tmp_str.strip(',') + "\n"

    def allocation_max_number(self, request):
        user = self.request.iser
        data_array = self.request.data.get('data_array', None)
        activity_id = self.request.data.get('activity_id', None)
        try:
            instance = self.get_queryset().get(id=activity_id)
        except:
            return Response({'error': '无效活动id'}, status=status.HTTP_400_BAD_REQUEST)
        template_id = instance.template_id
        redis_conn = get_redis_connection("default")
        template_id_server = redis_conn.get(template_id)
        if template_id_server:
            return Response({'error': "活动正在分配中,请稍候"}, status=status.HTTP_400_BAD_REQUEST)
        redis_conn.set(template_id, 1)
        level_list = get_level_list(user.level)
        level_range = instance.level.level
        p_alidiscountcouponlevel = AliDiscountCouponLevel.objects.filter(level_id=user.level_id, activity_id=instance.id).first()
        remain_number = p_alidiscountcouponlevel.remain_number
        max_number = p_alidiscountcouponlevel.max_number
        if instance.coupon_way == 1:
            if not data_array:
                redis_conn.delete(template_id)
                return Response({'error': '缺少分配参数'}, status=status.HTTP_400_BAD_REQUEST)
            # max_number__sum = instance.alidiscountcouponlevel_set.all().aggregate(Sum('max_number'))['max_number__sum']
            # if max_number__sum:
            #     remain_number = instance.max_number - max_number__sum
            # else:
            #     remain_number = instance.max_number
            with transaction.atomic():
                # 创建事务保存点
                save_id = transaction.savepoint()
                try:
                    queryset_list = []
                    for allot in data_array:
                        if int(allot['level_id']) not in level_list:
                            transaction.savepoint_rollback(save_id)
                            redis_conn.delete(template_id)
                            return Response({'error': '存在无权限机构'}, status=status.HTTP_400_BAD_REQUEST)
                        if int(allot['count']) < 0:
                            transaction.savepoint_rollback(save_id)
                            redis_conn.delete(template_id)
                            return Response({'error': '分配数量须大于0'}, status=status.HTTP_400_BAD_REQUEST)
                        if remain_number < int(allot['count']):
                            transaction.savepoint_rollback(save_id)
                            redis_conn.delete(template_id)
                            return Response({'error': '分配数据超过活动最大数'}, status=status.HTTP_400_BAD_REQUEST)
                        diacountcouponlevel_data = {}
                        diacountcouponlevel_data['level_id'] = allot['level_id']
                        diacountcouponlevel_data['activity_id'] = activity_id
                        diacountcouponlevel = AliDiscountCouponLevel.objects.filter(activity_id=activity_id, level_id=allot['level_id']).first()
                        if diacountcouponlevel and diacountcouponlevel.max_number != 0:
                            transaction.savepoint_rollback(save_id)
                            redis_conn.delete(template_id)
                            return Response({'error': f'{diacountcouponlevel.level.name}重复配置'}, status=status.HTTP_400_BAD_REQUEST)
                        if diacountcouponlevel:
                            diacountcouponlevel.max_number += int(allot['count'])
                            diacountcouponlevel.remain_number += int(allot['count'])
                            diacountcouponlevel.p_max_number += int(allot['count'])
                            diacountcouponlevel.p_remain_number += int(allot['count'])
                            diacountcouponlevel.save()
                        else:
                            diacountcouponlevel_data['max_number'] = int(allot['count'])
                            diacountcouponlevel_data['remain_number'] = int(allot['count'])
                            diacountcouponlevel_data['p_max_number'] = int(allot['count'])
                            diacountcouponlevel_data['p_remain_number'] = int(allot['count'])
                            diacountcouponlevel, create = AliDiscountCouponLevel.objects.get_or_create(defaults=diacountcouponlevel_data, activity_id=activity_id, level_id=allot['level_id'])
                        remain_number -= int(allot['count'])
                        max_number -= int(allot['count'])
                        queryset_list.append(diacountcouponlevel.id)
                    p_alidiscountcouponlevel.max_number = max_number
                    p_alidiscountcouponlevel.remain_number = remain_number
                    p_alidiscountcouponlevel.save()
                    level_level_list = []
                    for i in range(4, level_range, -1):
                        level_level_list.append(i)
                        queryset = AliDiscountCouponLevel.objects.filter(id__in=queryset_list, level__level__in=level_level_list)
                        for query in queryset:
                            query_level = query.level
                            if i == 4:
                                diacountcouponlevel_level_id = query_level.parent_id
                            elif i == 3:
                                if query_level.level == 4:
                                    diacountcouponlevel_level_id = query_level.parent.parent_id
                                else:
                                    diacountcouponlevel_level_id = query_level.parent_id
                            elif i == 2:
                                if query_level.level == 4:
                                    diacountcouponlevel_level_id = query_level.parent.parent.parent_id
                                elif query_level.level == 3:
                                    diacountcouponlevel_level_id = query_level.parent.parent_id
                                else:
                                    diacountcouponlevel_level_id = query_level.parent_id
                            else:
                                if query_level.level == 4:
                                    diacountcouponlevel_level_id = query_level.parent.parent.parent.parent_id
                                elif query_level.level == 3:
                                    diacountcouponlevel_level_id = query_level.parent.parent.parent_id
                                elif query_level.level == 2:
                                    diacountcouponlevel_level_id = query_level.parent.parent_id
                                else:
                                    diacountcouponlevel_level_id = query_level.parent_id
                            instance1 = AliDiscountCouponLevel.objects.filter(level_id=diacountcouponlevel_level_id, activity_id=activity_id).first()
                            if not instance1:
                                instance1 = AliDiscountCouponLevel.objects.create(level_id=diacountcouponlevel_level_id, activity_id=activity_id, max_number=0)
                            queryset_list.append(instance1.id)
                            if instance1.level.level > p_alidiscountcouponlevel.level.level:
                                p_max_number = instance1.p_max_number + query.max_number
                                p_remain_number = instance1.p_remain_number + query.remain_number
                                instance1.p_max_number = p_max_number
                                instance1.p_remain_number = p_remain_number
                                instance1.save()
                            relation_data = {
                                "parent_id": instance1.id,
                                "child_id": query.id
                            }
                            AliDiscountCouponLevelRelation.objects.get_or_create(defaults=relation_data, parent_id=instance1.id, child_id=query.id)
                except Exception as e:
                    logger.error(e)
                    transaction.savepoint_rollback(save_id)
                    redis_conn.delete(template_id)
                    return Response({'error': '分配失败,请联系管理员'}, status=status.HTTP_400_BAD_REQUEST)
                transaction.savepoint_commit(save_id)
                redis_conn.delete(template_id)
                return Response({'success': '分配成功'}, status=status.HTTP_200_OK)
        elif instance.coupon_way == 4:
            if not data_array:
                redis_conn.delete(template_id)
                return Response({'error': '缺少分配参数'}, status=status.HTTP_400_BAD_REQUEST)
            with transaction.atomic():
                # 创建事务保存点
                save_id = transaction.savepoint()
                try:
                    for level_id in data_array:
                        if int(level_id) not in level_list:
                            transaction.savepoint_rollback(save_id)
                            redis_conn.delete(template_id)
                            return Response({'error': '存在无权限机构'}, status=status.HTTP_400_BAD_REQUEST)
                        diacountcouponlevel = AliDiscountCouponLevel.objects.filter(activity_id=activity_id, level_id=level_id).first()
                        if diacountcouponlevel:
                            diacountcouponlevel.is_auth = 1
                            diacountcouponlevel.save()
                        else:
                            diacountcouponlevel_data = {}
                            diacountcouponlevel_data['level_id'] = level_id
                            diacountcouponlevel_data['activity_id'] = activity_id
                            diacountcouponlevel_data['is_auth'] = 1
                            diacountcouponlevel, create = AliDiscountCouponLevel.objects.get_or_create(activity_id=activity_id, level_id=level_id, defaults=diacountcouponlevel_data)
                            level_level_list = []
                            queryset_list = []
                            queryset_list.append(diacountcouponlevel.id)
                            for i in range(4, level_range, -1):
                                level_level_list.append(i)
                                queryset = AliDiscountCouponLevel.objects.filter(id__in=queryset_list, level__level__in=level_level_list)
                                for query in queryset:
                                    query_level = query.level
                                    if i == 4:
                                        diacountcouponlevel_level_id = query_level.parent_id
                                    elif i == 3:
                                        if query_level.level == 4:
                                            diacountcouponlevel_level_id = query_level.parent.parent_id
                                        else:
                                            diacountcouponlevel_level_id = query_level.parent_id
                                    elif i == 2:
                                        if query_level.level == 4:
                                            diacountcouponlevel_level_id = query_level.parent.parent.parent_id
                                        elif query_level.level == 3:
                                            diacountcouponlevel_level_id = query_level.parent.parent_id
                                        else:
                                            diacountcouponlevel_level_id = query_level.parent_id
                                    else:
                                        if query_level.level == 4:
                                            diacountcouponlevel_level_id = query_level.parent.parent.parent.parent_id
                                        elif query_level.level == 3:
                                            diacountcouponlevel_level_id = query_level.parent.parent.parent_id
                                        elif query_level.level == 2:
                                            diacountcouponlevel_level_id = query_level.parent.parent_id
                                        else:
                                            diacountcouponlevel_level_id = query_level.parent_id
                                    instance1 = AliDiscountCouponLevel.objects.filter(level_id=diacountcouponlevel_level_id, activity_id=activity_id).first()
                                    if not instance1:
                                        instance1 = AliDiscountCouponLevel.objects.create(level_id=diacountcouponlevel_level_id, activity_id=activity_id, max_number=0)
                                    queryset_list.append(instance1.id)
                                    relation_data = {
                                        "parent_id": instance1.id,
                                        "child_id": query.id
                                    }
                                    AliDiscountCouponLevelRelation.objects.get_or_create(defaults=relation_data, parent_id=instance1.id, child_id=query.id)
                except Exception as e:
                    logger.error(e)
                    transaction.savepoint_rollback(save_id)
                    redis_conn.delete(template_id)
                    return Response({'error': '分配失败,请联系管理员'}, status=status.HTTP_400_BAD_REQUEST)
                transaction.savepoint_commit(save_id)
                redis_conn.delete(template_id)
                return Response({'success': '分配成功'}, status=status.HTTP_200_OK)
        else:
            redis_conn.delete(template_id)
            return Response({'error': '当前活动类型不允许分配'}, status=status.HTTP_400_BAD_REQUEST)

    def allocation_level(self, request):
        user = self.request.iser
        activity_id = self.request.query_params.get('activity_id', None)
        search = self.request.query_params.get('search', None)
        if not activity_id:
            return Response({'error': '请传活动id'}, status=status.HTTP_400_BAD_REQUEST)
        try:
            activity = self.get_queryset().get(id=activity_id)
        except:
            return Response({'error': '无效活动id'}, status=status.HTTP_400_BAD_REQUEST)
        try:
            alidiscountcouponlevel = AliDiscountCouponLevel.objects.filter(level_id=user.level_id, activity_id=activity.id).first()
            can_remain_number = alidiscountcouponlevel.remain_number
        except:
            can_remain_number = 0
        try:
            if '_mutable' in self.request.data.__dict__:
                self.request.data.__dict__['_mutable'] = True
        except:
            pass
        self.request.data['can_remain_number'] = str(can_remain_number)
        level = user.level
        if level.level == 0:
            queryset = Level.objects.all().order_by('level')
        elif level.level == 1:
            queryset = Level.objects.filter(prov_id=level.id).order_by('level')
        elif level.level == 2:
            queryset = Level.objects.filter(city_id=level.id).order_by('level')
        elif level.level == 3:
            queryset = Level.objects.filter(district_id=level.id).order_by('level')
        else:
            queryset = Level.objects.filter(branch_id=level.id).order_by('level')
        queryset = queryset.exclude(alidiscountcouponlevel__activity_id=activity_id)
        if search:
            queryset = queryset.filter(Q(name__contains=search) | Q(account__contains=search))
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = LevelListSerializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        serializer = LevelListSerializer(queryset, many=True)
        return Response(serializer.data)

    def update_merchant(self, request):
        return Response({'error': '功能暂未开放，敬请期待'}, status=status.HTTP_400_BAD_REQUEST)
        activity_id = self.request.data.get('activity_id', None)
        merchant_array = self.request.data.get('merchant_array', None)
        user = self.request.iser
        try:
            instance = self.get_queryset().get(id=activity_id)
        except:
            return Response({'error': '无效活动id'}, status=status.HTTP_400_BAD_REQUEST)
        if not isinstance(merchant_array, list):
            return Response({'error': '参数类型有误'}, status=status.HTTP_400_BAD_REQUEST)
        line_number = len(merchant_array)
        if line_number > 2000:
            return Response({'error': '最大添加商户数不得超过2000'}, status=status.HTTP_400_BAD_REQUEST)
        if instance.coupon_channel != 2:
            return Response({'error': '仅支持微信代金券活动'}, status=status.HTTP_400_BAD_REQUEST)
        try:
            updatestockusablemerchant_data = {}
            updatestockusablemerchant_data['user_id'] = user.id
            updatestockusablemerchant_data['test'] = json.dumps(merchant_array)
            updatestockusablemerchant_data['add_type'] = 2
            updatestockusablemerchant_data['alidiscountcoupon_id'] = instance.id
            updatestockusablemerchant_data['wx_is_enter'] = 6
            updatestockusablemerchant_data['ylx_is_enter'] = 6
            updatestockusablemerchant_data['apply_state'] = 1
            updatestockusablemerchant_data['line_number'] = line_number
            l2 = []
            template_id = instance.template_id
            table_title = ['批次号', '商户号']
            l2.append(table_title)
            for merchant in merchant_array:
                table_body = []
                table_body.append(template_id)
                table_body.append(merchant)
                l2.append(table_body)
            book = f'{instance.activity_name}_{datetime.datetime.now().strftime("%Y%m%d%H%M%S")}'
            book_name = f'{book}.xlsx'
            book_name_xlsx = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), f'static/{book_name}')
            sheet_name_xlsx = 'Sheet1'
            write_excel_xlsx(book_name_xlsx, sheet_name_xlsx, l2)
            with open(book_name_xlsx, 'rb') as f:
                file_contents = f.read()
            file = pic_upload(file_contents, book_name)
            updatestockusablemerchant_data['file'] = file
            history = UpdateStockUsableMerchant.objects.create(**updatestockusablemerchant_data)
            os.remove(book_name_xlsx)
            return Response({'success': '提交修改成功,等待系统处理'}, status=status.HTTP_200_OK)
        except:
            return Response({'error': '提交失败,请联系管理员'}, status=status.HTTP_400_BAD_REQUEST)


class UpdateStockUsableMerchantModelViewSet(ModelViewSet):

    pagination_class = MyPage
    filter_class = UpdateStockUsableMerchantFilter
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)
    # search_fields = ('customer_user__mobile', )
    serializer_class = UpdateStockUsableMerchantModelSerializer

    def get_queryset(self):
        user = self.request.iser
        queryset = UpdateStockUsableMerchant.objects.filter(user_id=user.id).exclude(add_type=3).order_by('-id')
        return queryset


class AliDiscountCouponLevelModelViewSet(ModelViewSet):

    pagination_class = MyPage
    search_fields = ('level__name', )
    filter_class = AliDiscountCouponLevelFilter
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)

    def get_queryset(self):
        user = self.request.iser
        level = user.level
        level_id = self.request.query_params.get('level', None)
        sort = self.request.query_params.get('sort', '')
        activity_id = self.request.query_params.get('activity_id', None)
        # if activity_id:
        #     try:
        #         activity = AliDiscountCoupon.objects.get(id=activity_id)
        #         max_number__sum = activity.alidiscountcouponlevel_set.all().aggregate(Sum('max_number'))['max_number__sum']
        #         if max_number__sum:
        #             remain_number = activity.max_number - max_number__sum
        #         else:
        #             remain_number = activity.max_number
        #         if '_mutable' in self.request.data.__dict__:
        #             self.request.data.__dict__['_mutable'] = True
        #         self.request.data['can_remain_number'] = str(remain_number)
        #     except:
        #         pass
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        if level.level == 0:
            queryset = AliDiscountCouponLevel.objects.all()
        elif level.level == 1:
            queryset = AliDiscountCouponLevel.objects.filter(level__prov_id=level.id)
        elif level.level == 2:
            queryset = AliDiscountCouponLevel.objects.filter(level__city_id=level.id)
        elif level.level == 3:
            queryset = AliDiscountCouponLevel.objects.filter(level__district_id=level.id)
        else:
            queryset = AliDiscountCouponLevel.objects.filter(level__branch_id=level.id)
        if not activity_id:
            city_list = list(AliDiscountCoupon.objects.filter(alidiscountcouponlevel__level_id=level.id).values_list('id', flat=True))
            queryset = queryset.filter(activity_id__in=city_list)
        if sort == '0':
            queryset = queryset.order_by('p_max_number', 'id')
        elif sort == '1':
            queryset = queryset.order_by('-p_max_number', 'id')
        elif sort == '2':
            queryset = queryset.order_by('p_take_number', 'id')
        elif sort == '3':
            queryset = queryset.order_by('-p_take_number', 'id')
        elif sort == '4':
            queryset = queryset.order_by('p_remain_number', 'id')
        elif sort == '5':
            queryset = queryset.order_by('-p_remain_number', 'id')
        elif sort == '6':
            queryset = queryset.order_by(F('p_take_number') - F('p_receive_number'), 'id')
        elif sort == '7':
            queryset = queryset.order_by(-(F('p_take_number') - F('p_receive_number')), 'id')
        elif sort == '8':
            queryset = queryset.order_by(F('p_receive_number') - F('p_use_number'), 'id')
        elif sort == '9':
            queryset = queryset.order_by(-(F('p_receive_number') - F('p_use_number')), 'id')
        elif sort == '10':
            queryset = queryset.order_by('p_use_number', 'id')
        elif sort == '11':
            queryset = queryset.order_by('-p_use_number', 'id')
        else:
            queryset = queryset.order_by('level__level', 'id')
        return queryset

    def get_serializer_context(self):
        user = self.request.iser
        return {'user': user}

    def get_serializer_class(self):
        if self.action == 'list':
            return AliDiscountCouponLevelListModelSerializer
        else:
            return AliDiscountCouponLevelRetrieveModelSerializer

    def up_file(self, request):
        my_file = self.request.FILES.get('my_file', None)

    def export_couponlevel(self, request):
        activity_id = self.request.query_params.get('activity_id', None)
        search = self.request.query_params.get('search', None)
        user = self.request.iser
        if not search:
            if user.level.level == 0:
                condition = ''
            elif user.level.level == 1:
                condition = f'WHERE prov_id={user.id}'
            elif user.level.level == 2:
                condition = f'WHERE city_id={user.id}'
            elif user.level.level == 3:
                condition = f'WHERE district_id={user.id}'
            else:
                condition = f'WHERE branch_id={user.id}'
        else:
            if user.level.level == 0:
                condition = f'WHERE name LIKE "%{search}%"'
            elif user.level.level == 1:
                condition = f'WHERE prov_id={user.id} AND name LIKE "%{search}%"'
            elif user.level.level == 2:
                condition = f'WHERE city_id={user.id} AND name LIKE "%{search}%"'
            elif user.level.level == 3:
                condition = f'WHERE district_id={user.id} AND name LIKE "%{search}%"'
            else:
                condition = f'WHERE branch_id={user.id} AND name LIKE "%{search}%"'
        if not activity_id:
            condition1 = ''
        else:
            condition1 = f'AND activity_id="{activity_id}"'
        conn = pymysql.connect(host=settings.DATABASES['default']['HOST'],
                               port=settings.DATABASES['default']['PORT'],
                               database=settings.DATABASES['default']['NAME'],
                               user=settings.DATABASES['default']['USER'],
                               password=settings.DATABASES['default']['PASSWORD'])
        cursor = conn.cursor(cursor=pymysql.cursors.SSDictCursor)
        sql = f'''
        SELECT c.*,d.activity_name FROM (SELECT a.*,b.name,account,prov_name,city_name,district_name,branch_name FROM (SELECT id,activity_id,max_number,take_number,remain_number,receive_number,use_number,level_id,(take_number-receive_number)AS unclaimed_number,(receive_number-use_number)AS wait_number FROM tb_ali_discount_coupon_level WHERE max_number!=0 AND level_id IN (SELECT id FROM tb_u_level {condition}) {condition1})AS a LEFT JOIN (SELECT id,name,account,prov_name,city_name,district_name,branch_name FROM tb_u_level)AS b ON a.level_id=b.id)AS c LEFT JOIN (SELECT id,activity_name FROM tb_ali_discount_coupon)AS d ON c.activity_id=d.id;
        '''
        cursor.execute(sql)
        ziduan = ['id', '活动名称', '机构名称', '机构号', '省', '市', '区县', '网点', '总额度', '已派发额度', '剩余额度', '待领取', '待核销', '已核销']
        cols = ['id', 'activity_name', 'name', 'account', 'prov_name', 'city_name', 'district_name', 'branch_name', 'max_number', 'take_number', 'remain_number', 'unclaimed_number',
                'wait_number', 'use_number']
        response = StreamingHttpResponse(self.get_couponlevel_fromat(cols, cursor, conn, ziduan))
        response['Content-Type'] = 'application/octet-stream; charset=gbk'
        response['Content-Disposition'] = "attachment; filename*=utf-8''{}".format(escape_uri_path('支付宝代金券机构领用汇总.csv'))
        return response

    def get_couponlevel_fromat(self, cols, cursor, conn, ziduan):
        tmp_str = ""
        # 返回文件的每一列列名
        for col in ziduan:
            tmp_str += '"%s",' % (col)
        yield tmp_str.strip(",") + "\n"
        while True:
            tmp_str = ""
            row = cursor.fetchone()
            if row is None:
                cursor.close()
                conn.close()
                break
            for col in cols:
                # if col == 'unclaimed_number':
                #     tmp_str += '"%s",' % (row['take_number']-row['receive_number'])
                # elif col == 'wait_number':
                #     tmp_str += '"%s",' % (row['receive_number']-row['use_number'])
                if col in ['max_number', 'take_number', 'remain_number', 'unclaimed_number', 'wait_number', 'use_number']:
                    tmp_str += '"%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else 0)
                else:
                    tmp_str += '"%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
            yield tmp_str.strip(',') + "\n"

    def batch_update_max_number(self, request):
        data_array = self.request.data.get('data_array', None)
        if not data_array:
            return Response({'error': '缺少必传参数'}, status=status.HTTP_400_BAD_REQUEST)
        if not isinstance(data_array, list):
            return Response({'error': '参数格式有误'}, status=status.HTTP_400_BAD_REQUEST)
        with transaction.atomic():
            # 创建事务保存点
            save_id = transaction.savepoint()

            # 暴力回滚
            try:
                for data in data_array:
                    instance = AliDiscountCouponLevel.objects.get(id=data['id'])

                    count = -int(data['count'])
                    if count < 0 and instance.remain_number < abs(count):
                        transaction.savepoint_rollback(save_id)
                        return Response({'error': f'{instance.id}剩余数量不足扣减'}, status=status.HTTP_400_BAD_REQUEST)
                    activity = instance.activity
                    instance.max_number = instance.max_number + count
                    instance.remain_number = instance.remain_number + count
                    instance.p_max_number = instance.p_max_number + count
                    instance.p_remain_number = instance.p_remain_number + count
                    instance.save()
                    activity.max_number += count
                    activity.remain_number += count
                    activity.save()
                    relation_set = instance.child_set.all()
                    for relation in relation_set:
                        parent = relation.parent
                        parent.p_max_number += count
                        parent.p_remain_number += count
                        parent.save()
            except Exception as e:
                logger.error(e)
                # 事务回滚
                transaction.savepoint_rollback(save_id)
                return Response({'error': '修改失败'}, status=status.HTTP_400_BAD_REQUEST)
        transaction.savepoint_commit(save_id)
        return Response({'success': '操作成功'}, status=status.HTTP_200_OK)

    def update(self, request, *args, **kwargs):
        user = self.request.iser
        instance = self.get_object()
        max_number = self.request.data.get('max_number', None)
        try:
            max_number = int(max_number)
        except:
            return Response({'error': '请输入整数额度'}, status=status.HTTP_400_BAD_REQUEST)
        activity = instance.activity
        if activity.coupon_way != 1:
            return Response({'error': '仅员工派券活动可调整派发额度'}, status=status.HTTP_400_BAD_REQUEST)
        if activity.coupon_status == 2:
            return Response({'error': '已结束活动不可操作'}, status=status.HTTP_400_BAD_REQUEST)
        p_instance = AliDiscountCouponLevel.objects.filter(level_id=user.level_id, activity_id=activity.id).first()
        instance_id = instance.id
        p_instance_id = p_instance.id
        if p_instance == instance:
            return Response({'error': '您无权限操作此层级'}, status=status.HTTP_400_BAD_REQUEST)
        with transaction.atomic():
            # 创建事务保存点
            save_id = transaction.savepoint()
            try:
                while True:
                    instance = AliDiscountCouponLevel.objects.get(id=instance_id)
                    p_instance = AliDiscountCouponLevel.objects.get(id=p_instance_id)
                    count = max_number - instance.max_number
                    if count > 0:
                        remain_number = p_instance.remain_number
                        max_number = p_instance.max_number
                        if remain_number < count:
                            transaction.savepoint_rollback(save_id)
                            return Response({'error': '活动额度不足'}, status=status.HTTP_400_BAD_REQUEST)
                    else:
                        if instance.remain_number < -count:
                            return Response({'error': '机构活动额度不足'}, status=status.HTTP_400_BAD_REQUEST)
                    origin_remain_number = instance.remain_number
                    origin_max_number = instance.max_number
                    origin_p_remain_number = instance.p_remain_number
                    origin_p_max_number = instance.p_max_number
                    new_remain_number = origin_remain_number + count
                    new_max_number = origin_max_number + count
                    new_p_remain_number = origin_p_remain_number + count
                    new_p_max_number = origin_p_max_number + count
                    result = AliDiscountCouponLevel.objects.filter(id=instance_id, remain_number=origin_remain_number).update(
                        max_number=new_max_number,
                        remain_number=new_remain_number,
                        p_max_number=new_p_max_number,
                        p_remain_number=new_p_remain_number
                    )
                    if result == 0:
                        continue
                    break
                while True:
                    p_instance = AliDiscountCouponLevel.objects.get(id=p_instance_id)
                    p_origin_remain_number = p_instance.remain_number
                    p_origin_max_number = p_instance.max_number
                    p_new_remain_number = p_origin_remain_number - count
                    p_new_max_number = p_origin_max_number - count
                    result1 = AliDiscountCouponLevel.objects.filter(id=p_instance_id, remain_number=p_origin_remain_number).update(
                        max_number=p_new_max_number,
                        remain_number=p_new_remain_number
                    )
                    if result1 == 0:
                        continue
                    break
                relation_set = instance.child_set.all()
                for relation in relation_set:
                    parent = relation.parent
                    if p_instance.level.level < parent.level.level:
                        parent.p_max_number += count
                        parent.p_remain_number += count
                        parent.save()
            except Exception as e:
                logger.error(e)
                transaction.savepoint_rollback(save_id)
                return Response({'error': '调配失败,请联系管理员'}, status=status.HTTP_400_BAD_REQUEST)
            transaction.savepoint_commit(save_id)
            return Response({'success': '调配成功'}, status=status.HTTP_200_OK)

    def transfer_max_number(self, request):
        count = self.request.data.get('count', None)
        in_id = self.request.data.get('in_id', None)
        out_id = self.request.data.get('out_id', None)
        try:
            count = int(count)
        except:
            return Response({'error': '请输入整数额度'}, status=status.HTTP_400_BAD_REQUEST)
        if count <= 0:
            return Response({'error': '请输入正整数额度'}, status=status.HTTP_400_BAD_REQUEST)
        queryset = self.get_queryset()
        try:
            in_instance = queryset.get(id=in_id)
        except:
            return Response({'error': '无效转入id'}, status=status.HTTP_400_BAD_REQUEST)
        try:
            out_instance = queryset.get(id=out_id)
        except:
            return Response({'error': '无效转出id'}, status=status.HTTP_400_BAD_REQUEST)
        if in_instance.activity_id != out_instance.activity_id:
            return Response({'error': '不同活动之间不允许转让'}, status=status.HTTP_400_BAD_REQUEST)
        with transaction.atomic():
            save_id = transaction.savepoint()
            try:
                while True:
                    in_instance = queryset.get(id=in_id)
                    out_instance = queryset.get(id=out_id)
                    if out_instance.remain_number < count:
                        transaction.savepoint_rollback(save_id)
                        return Response({'error': '转出机构额度不足'}, status=status.HTTP_400_BAD_REQUEST)
                    in_origin_remain_number = in_instance.remain_number
                    in_origin_max_number = in_instance.max_number
                    in_origin_p_remain_number = in_instance.p_remain_number
                    in_origin_p_max_number = in_instance.p_max_number
                    in_new_remain_number = in_origin_remain_number + count
                    in_new_max_number = in_origin_max_number + count
                    in_new_p_remain_number = in_origin_p_remain_number + count
                    in_new_p_max_number = in_origin_p_max_number + count
                    in_result = AliDiscountCouponLevel.objects.filter(id=in_id, remain_number=in_origin_remain_number).update(
                        max_number=in_new_max_number,
                        remain_number=in_new_remain_number,
                        p_max_number=in_new_p_max_number,
                        p_remain_number=in_new_p_remain_number
                    )
                    out_origin_remain_number = out_instance.remain_number
                    out_origin_max_number = out_instance.max_number
                    out_origin_p_remain_number = out_instance.p_remain_number
                    out_origin_p_max_number = out_instance.p_max_number
                    out_new_remain_number = out_origin_remain_number - count
                    out_new_max_number = out_origin_max_number - count
                    out_new_p_remain_number = out_origin_p_remain_number - count
                    out_new_p_max_number = out_origin_p_max_number - count
                    out_result = AliDiscountCouponLevel.objects.filter(id=out_id, remain_number=out_origin_remain_number).update(
                        max_number=out_new_max_number,
                        remain_number=out_new_remain_number,
                        p_max_number=out_new_p_max_number,
                        p_remain_number=out_new_p_remain_number
                    )
                    if in_result == 0 or out_result == 0:
                        continue
                    break
                in_relation_set = in_instance.child_set.all()
                for relation in in_relation_set:
                    parent = relation.parent
                    parent.p_max_number += count
                    parent.p_remain_number += count
                    parent.save()
                out_relation_set = out_instance.child_set.all()
                for relation in out_relation_set:
                    parent = relation.parent
                    parent.p_max_number -= count
                    parent.p_remain_number -= count
                    parent.save()
            except Exception as e:
                logger.error(e)
                transaction.savepoint_rollback(save_id)
                return Response({'error': '转让失败,请联系管理员'}, status=status.HTTP_400_BAD_REQUEST)
            transaction.savepoint_commit(save_id)
            return Response({'success': '转让成功'}, status=status.HTTP_200_OK)


class MerchantBillModelViewSet(ModelViewSet):

    pagination_class = MyPage
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)
    search_fields = ('merchant__name', 'merchant__wyfMerchantID')
    filter_class = MerchantBillFilter

    def get_queryset(self):
        user = self.request.iser
        level = user.level
        level_id = self.request.query_params.get('level', None)
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        if level.level == 0:
            queryset = MerchantBill.objects.all().order_by('-receipts_time')
        elif level.level == 1:
            queryset = MerchantBill.objects.filter(level__prov_id=level.id).order_by('-receipts_time')
        elif level.level == 2:
            queryset = MerchantBill.objects.filter(level__city_id=level.id).order_by('-receipts_time')
        elif level.level == 3:
            queryset = MerchantBill.objects.filter(level__district_id=level.id).order_by('-receipts_time')
        else:
            queryset = MerchantBill.objects.filter(level__branch_id=level.id).order_by('-receipts_time')
        queryset = queryset.filter(receipts_time__gte="2023-01-01 00:00:00")
        return queryset.distinct()

    def get_serializer_class(self):
        if self.action == 'list':
            return MerchantBillListModelSerializer
        else:
            return MerchantBillRetrieveModelSerializer

    def export_merchant_bill(self, request):
        user = self.request.iser
        receipts_time_end = self.request.query_params.get('receipts_time_end', None)
        receipts_time_begin = self.request.query_params.get('receipts_time_begin', None)
        settlement_time_end = self.request.query_params.get('settlement_time_end', None)
        settlement_time_begin = self.request.query_params.get('settlement_time_begin', None)
        payable_amount_min = self.request.query_params.get('payable_amount_min', None)
        payable_amount_max = self.request.query_params.get('payable_amount_max', None)
        level_id = self.request.query_params.get('level', None)
        bill_state = self.request.query_params.get('bill_state', None)
        search = self.request.query_params.get('search', None)
        bill_type = self.request.query_params.get('bill_type', None)
        level = user.level
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        if level.level == 0:
            condition = 'WHERE level_id IN (SELECT id FROM tb_u_level)'
        elif level.level == 1:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE prov_id={level.id})'
        elif level.level == 2:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE city_id={level.id})'
        elif level.level == 3:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE district_id={level.id})'
        else:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE branch_id={level.id})'
        if search:
            condition = condition + f' AND (merchant_id IN (SELECT id FROM tb_merchant WHERE name LIKE "%{search}%" OR short_name LIKE "%{search}%" OR wyfMerchantID LIKE "%{search}%"))'
        if bill_state:
            condition = condition + f' AND bill_state in ({bill_state})'
        if bill_type:
            condition = condition + f' AND bill_type in ({bill_type})'
        if receipts_time_begin:
            condition = condition + f' AND receipts_time >= "{receipts_time_begin + " 00:00:00"}"'
        if receipts_time_end:
            condition = condition + f' AND receipts_time <= "{receipts_time_end + " 23:59:59"}"'
        if settlement_time_begin:
            condition = condition + f' AND settlement_time >= "{settlement_time_begin + " 00:00:00"}"'
        if settlement_time_end:
            condition = condition + f' AND settlement_time <= "{settlement_time_end + " 23:59:59"}"'
        if payable_amount_min:
            condition = condition + f' AND payable_amount >= "{payable_amount_min}"'
        if payable_amount_max:
            condition = condition + f' AND payable_amount <= "{payable_amount_max}"'
        conn = pymysql.connect(host=settings.DATABASES['default']['HOST'],
                               port=settings.DATABASES['default']['PORT'],
                               database=settings.DATABASES['default']['NAME'],
                               user=settings.DATABASES['default']['USER'],
                               password=settings.DATABASES['default']['PASSWORD'])
        cursor = conn.cursor(cursor=pymysql.cursors.SSDictCursor)
        try:
            sql = f'''
            SELECT e.*,f.channel_name FROM (SELECT c.*,d.city_name,district_name,branch_name FROM (SELECT a.*,b.name,short_name,wyfMerchantID FROM (SELECT id,merchant_id,DATE_FORMAT(receipts_time,'%Y-%m-%d')AS receipts_time,DATE_FORMAT(settlement_time,'%Y-%m-%d %H:%i:%S')AS settlement_time,payable_amount,bill_state,account_bank,account_name,account_number,settlement_amount,level_id,channel_id,other_amount,other_commission,other_settlement_amount FROM tb_merchant_bill {condition})AS a LEFT JOIN(SELECT id,name,short_name,wyfMerchantID FROM tb_merchant)AS b ON a.merchant_id=b.id)AS c LEFT JOIN (SELECT id,city_name,district_name,branch_name FROM tb_u_level)AS d ON c.level_id=d.id)AS e LEFT JOIN (SELECT id,name AS channel_name FROM tb_channel)AS f ON e.channel_id=f.id;
            '''
            cursor.execute(sql)
        except:
            sql = f'''
            SELECT e.*,f.channel_name FROM (SELECT c.*,d.city_name,district_name,branch_name FROM (SELECT a.*,b.name,short_name,wyfMerchantID FROM (SELECT id,merchant_id,DATE_FORMAT(receipts_time,'%Y-%m-%d')AS receipts_time,DATE_FORMAT(settlement_time,'%Y-%m-%d %H:%i:%S')AS settlement_time,payable_amount,bill_state,account_bank,account_name,account_number,settlement_amount,level_id,channel_id,other_amount,other_commission,other_settlement_amount FROM tb_merchant_bill)AS a LEFT JOIN(SELECT id,name,short_name,wyfMerchantID FROM tb_merchant)AS b ON a.merchant_id=b.id)AS c LEFT JOIN (SELECT id,city_name,district_name,branch_name FROM tb_u_level)AS d ON c.level_id=d.id)AS e LEFT JOIN (SELECT id,name AS channel_name FROM tb_channel)AS f ON e.channel_id=f.id;
            '''
            cursor.execute(sql)
        ziduan = ['结算ID', '商户全称', '商户简称', '微邮付商户号', '清分日期', '结算时间', '清分金额', '结算金额',
                  '结算状态', '归属市公司', '归属区县', '归属网点', '结算通道', '结算户名', '结算卡号', '微邮付交易金额',
                  '微邮付交易手续费', '微邮付结算金额']
        cols = ['id', 'name', 'short_name', 'wyfMerchantID', 'receipts_time', 'settlement_time', 'payable_amount', 'settlement_amount',
                'bill_state', 'city_name', 'district_name', 'branch_name', 'channel_name', 'account_name', 'account_number', 'other_amount',
                'other_commission', 'other_settlement_amount']
        response = StreamingHttpResponse(self.get_merchant_bill_fromat(cols, cursor, conn, ziduan))
        response['Content-Type'] = 'application/octet-stream; charset=gbk'
        response['Content-Disposition'] = "attachment; filename*=utf-8''{}".format(escape_uri_path('结算单信息.csv'))
        return response

    def get_merchant_bill_fromat(self, cols, cursor, conn, ziduan):
        tmp_str = ""
        # 返回文件的每一列列名
        for col in ziduan:
            tmp_str += '"%s",' % (col)
        yield tmp_str.strip(",") + "\n"
        STATUS_ENUM = {
            1: '待结算',
            2: '结算中',
            3: '已结算',
            4: '已撤销',
            5: '结算失败'
        }
        while True:
            tmp_str = ""
            row = cursor.fetchone()
            if row is None:
                cursor.close()
                conn.close()
                break
            for col in cols:
                if col == 'bill_state':
                    tmp_str += '"%s",' % (STATUS_ENUM[row[col]])
                elif col in ['other_commission', 'other_settlement_amount', 'other_amount']:
                    tmp_str += '"%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] != None else '-')
                else:
                    tmp_str += '"%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
            yield tmp_str.strip(',') + "\n"


class SpeedLoanUserInfoModelViewSet(ModelViewSet):

    def export_loanuserinfo(self, request):
        conn = pymysql.connect(host=settings.DATABASES['default']['HOST'],
                               port=settings.DATABASES['default']['PORT'],
                               database=settings.DATABASES['default']['NAME'],
                               user=settings.DATABASES['default']['USER'],
                               password=settings.DATABASES['default']['PASSWORD'])
        cursor = conn.cursor(cursor=pymysql.cursors.SSDictCursor)
        sql = f'''
        SELECT c.*,d.prov_name,city_name,district_name,branch_name FROM (SELECT a.*,b.name FROM (SELECT * FROM tb_speed_loan_user_info WHERE id>4)AS a LEFT JOIN (SELECT id,name FROM tb_speed_loan_industry)AS b ON a.industry_id=b.id)AS c LEFT JOIN (SELECT id,prov_name,city_name,district_name,branch_name FROM tb_u_level)AS d ON c.level_id=d.id;
        '''
        cursor.execute(sql)
        ziduan = ['id', '客户手机号码', '客户姓名', '年龄', '经营行业', '所在地区(省)', '所在地区(市)', '所在地区(区)', '详细地址', '经营年限', '是否有固定房产', '微邮付商户号(参考)',
                  '所属市公司', '所属区县', '所属网点']
        cols = ['id', 'mobile', 'realname', 'age', 'name', 'province', 'city', 'district', 'address', 'business_limit', 'is_house', 'business_no', 'city_name',
                'district_name', 'branch_name']
        response = StreamingHttpResponse(self.get_loanuserinfo_fromat(cols, cursor, conn, ziduan))
        response['Content-Type'] = 'application/octet-stream; charset=gbk'
        response['Content-Disposition'] = "attachment; filename*=utf-8''{}".format(escape_uri_path('极速贷商户信息.csv'))
        return response

    def get_loanuserinfo_fromat(self, cols, cursor, conn, ziduan):
        tmp_str = ""
        # 返回文件的每一列列名
        for col in ziduan:
            tmp_str += '"%s",' % (col)
        yield tmp_str.strip(",") + "\n"
        IS_HOUSE_ENUM = {
            0: '否',
            1: '是'
        }
        while True:
            tmp_str = ""
            row = cursor.fetchone()
            if row is None:
                cursor.close()
                conn.close()
                break
            for col in cols:
                if col == 'is_house':
                    tmp_str += '"%s",' % (IS_HOUSE_ENUM[row[col]])
                elif col in ['age']:
                    tmp_str += '"%s"岁,' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
                elif col in ['business_limit']:
                    tmp_str += '"%s"年,' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
                else:
                    tmp_str += '"%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
            yield tmp_str.strip(',') + "\n"


class GoodsModifyApplymentModelViewSet(ModelViewSet):

    def get_queryset(self):
        queryset = GoodsModifyApplyment.objects.all()
        return queryset

    # def get_serializer_class(self):


class ChannelModelViewSet(ModelViewSet):

    serializer_class = ChannelModelSerializer
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)
    search_fields = ('name', )
    filter_class = ChannelFilter

    def get_queryset(self):
        queryset = Channel.objects.all()
        return queryset


class CashActivityModelViewSet(ModelViewSet):

    pagination_class = MyPage
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)
    search_fields = ('name', )
    filter_class = CashActivityFilter

    def get_queryset(self):
        today = datetime.datetime.now()
        user = self.request.iser
        level = user.level
        queryset = CashActivity.objects.filter(cashactivitylevel__level_id=level.id)
        return queryset.filter(available_end_time__gte=today).exclude(activity_state=1).order_by('-id')

    def get_serializer_class(self):
        if self.action == 'list':
            return CashActivityListModelSerializer
        else:
            return CashActivityRetrieveModelSerializer

    def get_serializer_context(self):
        user = self.request.iser
        return {'user': user}

    def partial_update(self, request, *args, **kwargs):
        instance = self.get_object()
        activity_state = self.request.data.get('activity_state', None)
        if instance.activity_state == 4:
            return Response({'error': '活动已结束, 不可操作'}, status=status.HTTP_400_BAD_REQUEST)
        if str(activity_state) == '1':
            instance.activity_state = 2
            instance.save()
            return Response({'success': '开启活动成功'}, status=status.HTTP_200_OK)
        elif str(activity_state) == '2':
            instance.activity_state = 3
            instance.save()
            return Response({'success': '暂停活动成功'}, status=status.HTTP_200_OK)
        else:
            return Response({'error': '无效活动状态'}, status=status.HTTP_400_BAD_REQUEST)

    def allocation_max_amount(self, request):
        user = self.request.iser
        data_array = self.request.data.get('data_array', None)
        cash_activity_id = self.request.data.get('cash_activity_id', None)
        try:
            instance = self.get_queryset().get(id=cash_activity_id)
        except:
            return Response({'error': '无效活动id'}, status=status.HTTP_400_BAD_REQUEST)
        if not data_array:
            return Response({'error': '缺少必传参数'}, status=status.HTTP_400_BAD_REQUEST)
        if not isinstance(data_array, list):
            return Response({'error': '参数格式有误'}, status=status.HTTP_400_BAD_REQUEST)
        if instance.activity_state == 4:
            return Response({'error': '已结束活动不可操作'}, status=status.HTTP_400_BAD_REQUEST)
        level_list = get_level_list(user.level)
        level_range = instance.level.level
        p_cashactivitylevel = CashActivityLevel.objects.filter(level_id=user.level_id, cash_activity_id=instance.id).first()
        remain_amount = p_cashactivitylevel.remain_amount
        max_amount = p_cashactivitylevel.max_amount
        with transaction.atomic():
            # 创建事务保存点
            save_id = transaction.savepoint()
            try:
                queryset_list = []
                for allot in data_array:
                    if int(allot['level_id']) not in level_list:
                        transaction.savepoint_rollback(save_id)
                        return Response({'error': '存在无权限机构'}, status=status.HTTP_400_BAD_REQUEST)
                    if Decimal(allot['amount']) <= 0:
                        transaction.savepoint_rollback(save_id)
                        return Response({'error': '分配数量须大于0'}, status=status.HTTP_400_BAD_REQUEST)
                    if remain_amount < Decimal(allot['amount']):
                        transaction.savepoint_rollback(save_id)
                        return Response({'error': '分配数据超过活动最大数'}, status=status.HTTP_400_BAD_REQUEST)
                    cashactivitylevel_data = {}
                    cashactivitylevel_data['level_id'] = allot['level_id']
                    cashactivitylevel_data['cash_activity_id'] = instance.id
                    cashactivitylevel = CashActivityLevel.objects.filter(cash_activity_id=instance.id, level_id=allot['level_id']).first()
                    if cashactivitylevel and cashactivitylevel.max_amount != 0:
                        transaction.savepoint_rollback(save_id)
                        return Response({'error': f'{cashactivitylevel.level.name}重复配置'}, status=status.HTTP_400_BAD_REQUEST)
                    if cashactivitylevel:
                        cashactivitylevel.max_amount += Decimal(allot['amount'])
                        cashactivitylevel.remain_amount += Decimal(allot['amount'])
                        cashactivitylevel.p_max_amount += Decimal(allot['amount'])
                        cashactivitylevel.p_remain_amount += Decimal(allot['amount'])
                        cashactivitylevel.save()
                    else:
                        cashactivitylevel_data['max_amount'] = Decimal(allot['amount'])
                        cashactivitylevel_data['remain_amount'] = Decimal(allot['amount'])
                        cashactivitylevel_data['p_max_amount'] = Decimal(allot['amount'])
                        cashactivitylevel_data['p_remain_amount'] = Decimal(allot['amount'])
                        cashactivitylevel_data['is_auth'] = 1
                        cashactivitylevel, create = CashActivityLevel.objects.get_or_create(defaults=cashactivitylevel_data, cash_activity_id=instance.id, level_id=allot['level_id'])
                    remain_amount -= Decimal(allot['amount'])
                    max_amount -= Decimal(allot['amount'])
                    queryset_list.append(cashactivitylevel.id)
                    try:
                        cashactivitylevelrecord_data = {}
                        cashactivitylevelrecord_data['activity_level_id'] = cashactivitylevel.id
                        cashactivitylevelrecord_data['amount'] = allot['amount']
                        cashactivitylevelrecord_data['operation_type'] = 3
                        cashactivitylevelrecord_data['remain_amount'] = cashactivitylevel.remain_amount
                        cashactivitylevelrecord_data['p_remain_amount'] = cashactivitylevel.p_remain_amount
                        cashactivitylevelrecord_data['max_amount'] = cashactivitylevel.max_amount
                        cashactivitylevelrecord_data['p_max_amount'] = cashactivitylevel.p_max_amount
                        cashactivitylevelrecord_data['user_id'] = user.id
                        cashactivitylevelrecord_data['remark'] = f'机构管理员通过后台分配:从{p_cashactivitylevel.level.name}获得'
                        cashactivitylevelrecord_data['activity_id'] = cashactivitylevel.cash_activity_id
                        CashActivityLevelRecord.objects.create(**cashactivitylevelrecord_data)

                        cashactivitylevelrecord_data = {}
                        cashactivitylevelrecord_data['activity_level_id'] = p_cashactivitylevel.id
                        cashactivitylevelrecord_data['amount'] = allot['amount']
                        cashactivitylevelrecord_data['operation_type'] = 4
                        cashactivitylevelrecord_data['remain_amount'] = remain_amount
                        cashactivitylevelrecord_data['p_remain_amount'] = p_cashactivitylevel.p_remain_amount
                        cashactivitylevelrecord_data['max_amount'] = max_amount
                        cashactivitylevelrecord_data['p_max_amount'] = p_cashactivitylevel.p_max_amount
                        cashactivitylevelrecord_data['user_id'] = user.id
                        cashactivitylevelrecord_data['remark'] = f'机构管理员通过后台分配:分配给{cashactivitylevel.level.name}'
                        cashactivitylevelrecord_data['activity_id'] = p_cashactivitylevel.cash_activity_id
                        CashActivityLevelRecord.objects.create(**cashactivitylevelrecord_data)
                    except Exception as e:
                        print(e)
                        pass
                p_cashactivitylevel.max_amount = max_amount
                p_cashactivitylevel.remain_amount = remain_amount
                p_cashactivitylevel.save()
                level_level_list = []
                for i in range(4, level_range, -1):
                    level_level_list.append(i)
                    queryset = CashActivityLevel.objects.filter(id__in=queryset_list, level__level__in=level_level_list)
                    for query in queryset:
                        query_level = query.level
                        if i == 4:
                            cashactivitylevel_level_id = query_level.parent_id
                        elif i == 3:
                            if query_level.level == 4:
                                cashactivitylevel_level_id = query_level.parent.parent_id
                            else:
                                cashactivitylevel_level_id = query_level.parent_id
                        elif i == 2:
                            if query_level.level == 4:
                                cashactivitylevel_level_id = query_level.parent.parent.parent_id
                            elif query_level.level == 3:
                                cashactivitylevel_level_id = query_level.parent.parent_id
                            else:
                                cashactivitylevel_level_id = query_level.parent_id
                        else:
                            if query_level.level == 4:
                                cashactivitylevel_level_id = query_level.parent.parent.parent.parent_id
                            elif query_level.level == 3:
                                cashactivitylevel_level_id = query_level.parent.parent.parent_id
                            elif query_level.level == 2:
                                cashactivitylevel_level_id = query_level.parent.parent_id
                            else:
                                cashactivitylevel_level_id = query_level.parent_id
                        instance1 = CashActivityLevel.objects.filter(level_id=cashactivitylevel_level_id, cash_activity_id=instance.id).first()
                        if not instance1:
                            instance1 = CashActivityLevel.objects.create(level_id=cashactivitylevel_level_id, cash_activity_id=instance.id, max_amount=0)
                        queryset_list.append(instance1.id)
                        if instance1.level.level > p_cashactivitylevel.level.level:
                            p_max_amount = instance1.p_max_amount + query.max_amount
                            p_remain_amount = instance1.p_remain_amount + query.remain_amount
                            instance1.p_max_amount = p_max_amount
                            instance1.p_remain_amount = p_remain_amount
                            instance1.save()
                        relation_data = {
                            "parent_id": instance1.id,
                            "child_id": query.id
                        }
                        CashActivityLevelRelation.objects.get_or_create(defaults=relation_data, parent_id=instance1.id, child_id=query.id)
            except Exception as e:
                logger.error(e)
                transaction.savepoint_rollback(save_id)
                return Response({'error': '分配失败,请联系管理员'}, status=status.HTTP_400_BAD_REQUEST)
            transaction.savepoint_commit(save_id)
            return Response({'success': '分配成功'}, status=status.HTTP_200_OK)

    def allocation_max_amount_level(self, request):
        user = self.request.iser
        cash_activity_id = self.request.query_params.get('cash_activity_id', None)
        search = self.request.query_params.get('search', None)
        if not cash_activity_id:
            return Response({'error': '请传活动id'}, status=status.HTTP_400_BAD_REQUEST)
        try:
            instance = self.get_queryset().get(id=cash_activity_id)
        except:
            return Response({'error': '无效活动id'}, status=status.HTTP_400_BAD_REQUEST)
        try:
            cashactivitylevel = CashActivityLevel.objects.filter(level_id=user.level_id, cash_activity_id=instance.id).first()
            can_remain_amount = cashactivitylevel.remain_amount
        except:
            can_remain_amount = 0
        try:
            if '_mutable' in self.request.data.__dict__:
                self.request.data.__dict__['_mutable'] = True
        except:
            pass
        self.request.data['can_remain_amount'] = str(can_remain_amount)
        level = user.level
        if level.level == 0:
            queryset = Level.objects.all().order_by('level')
        elif level.level == 1:
            queryset = Level.objects.filter(prov_id=level.id).order_by('level')
        elif level.level == 2:
            queryset = Level.objects.filter(city_id=level.id).order_by('level')
        elif level.level == 3:
            queryset = Level.objects.filter(district_id=level.id).order_by('level')
        else:
            queryset = Level.objects.filter(branch_id=level.id).order_by('level')
        queryset = queryset.exclude(cashactivitylevel__cash_activity_id=instance.id)
        if search:
            queryset = queryset.filter(Q(name__contains=search) | Q(account__contains=search))
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = LevelListSerializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        serializer = LevelListSerializer(queryset, many=True)
        return Response(serializer.data)

    def update(self, request, *args, **kwargs):
        user = self.request.iser
        instance = self.get_object()
        if instance.activity_state == 4:
            return Response({'error': '活动已结束, 不可操作'}, status=status.HTTP_400_BAD_REQUEST)
        if instance.activity_state != 3:
            return Response({'error': '请先暂停活动, 再执行该操作'}, status=status.HTTP_400_BAD_REQUEST)
        if instance.activity_type not in [1, 2, 3]:
            return Response({'error': '活动类型有误'}, status=status.HTTP_400_BAD_REQUEST)
        p_instance = CashActivityLevel.objects.filter(level_id=user.level_id, cash_activity_id=instance.id).first()
        # p_instance = CashActivityLevel.objects.get(level_id=user.level_id, cash_activity_id=instance.id)
        relation_set = p_instance.parent_set.all()
        p_instance_id = p_instance.id
        for relation in relation_set:
            child_id = relation.child_id
            with transaction.atomic():
                # 创建事务保存点
                save_id = transaction.savepoint()
                try:
                    while True:
                        child = CashActivityLevel.objects.get(id=child_id)
                        amount = child.remain_amount
                        if amount <= Decimal('0'):
                            break
                        operation_type = 4
                        p_operation_type = 3
                        remark = f'机构管理员通过后台分配:被{p_instance.level.name}回收'
                        p_remark = f'机构管理员通过后台分配:从{child.level.name}扣回'
                        origin_remain_amount = child.remain_amount
                        origin_max_amount = child.max_amount
                        origin_p_remain_amount = child.p_remain_amount
                        origin_p_max_amount = child.p_max_amount
                        new_remain_amount = origin_remain_amount - amount
                        new_max_amount = origin_max_amount - amount
                        new_p_remain_amount = origin_p_remain_amount - amount
                        new_p_max_amount = origin_p_max_amount - amount
                        result = CashActivityLevel.objects.filter(id=child_id, remain_amount=origin_remain_amount).update(max_amount=new_max_amount,remain_amount=new_remain_amount,p_max_amount=new_p_max_amount,p_remain_amount=new_p_remain_amount)
                        if result == 0:
                            continue
                        break
                    while True:
                        if amount <= Decimal('0'):
                            break
                        p_instance = CashActivityLevel.objects.get(id=p_instance_id)
                        p_origin_remain_amount = p_instance.remain_amount
                        p_origin_max_amount = p_instance.max_amount
                        p_new_remain_amount = p_origin_remain_amount + amount
                        p_new_max_amount = p_origin_max_amount + amount
                        result1 = CashActivityLevel.objects.filter(id=p_instance_id, remain_amount=p_origin_remain_amount).update(
                            max_amount=p_new_max_amount,
                            remain_amount=p_new_remain_amount
                        )
                        if result1 == 0:
                            continue
                        break
                    try:
                        if amount > Decimal('0'):
                            cashactivitylevelrecord_data = {}
                            cashactivitylevelrecord_data['activity_level_id'] = child.id
                            cashactivitylevelrecord_data['amount'] = -amount
                            cashactivitylevelrecord_data['operation_type'] = operation_type
                            cashactivitylevelrecord_data['remain_amount'] = new_remain_amount
                            cashactivitylevelrecord_data['p_remain_amount'] = new_p_remain_amount
                            cashactivitylevelrecord_data['max_amount'] = new_max_amount
                            cashactivitylevelrecord_data['p_max_amount'] = new_p_max_amount
                            cashactivitylevelrecord_data['user_id'] = user.id
                            cashactivitylevelrecord_data['remark'] = remark
                            cashactivitylevelrecord_data['activity_id'] = child.cash_activity_id
                            CashActivityLevelRecord.objects.create(**cashactivitylevelrecord_data)
                            cashactivitylevelrecord_data = {}
                            cashactivitylevelrecord_data['activity_level_id'] = p_instance.id
                            cashactivitylevelrecord_data['amount'] = amount
                            cashactivitylevelrecord_data['operation_type'] = p_operation_type
                            cashactivitylevelrecord_data['remain_amount'] = p_new_remain_amount
                            cashactivitylevelrecord_data['p_remain_amount'] = p_instance.p_remain_amount
                            cashactivitylevelrecord_data['max_amount'] = p_new_max_amount
                            cashactivitylevelrecord_data['p_max_amount'] = p_instance.p_max_amount
                            cashactivitylevelrecord_data['user_id'] = user.id
                            cashactivitylevelrecord_data['remark'] = p_remark
                            cashactivitylevelrecord_data['activity_id'] = p_instance.cash_activity_id
                            CashActivityLevelRecord.objects.create(**cashactivitylevelrecord_data)
                    except Exception as e:
                        print(e)
                        pass
                    relation_set = child.child_set.all()
                    for relation in relation_set:
                        parent = relation.parent
                        if p_instance.level.level < parent.level.level:
                            parent.p_max_amount -= amount
                            parent.p_remain_amount -= amount
                            parent.save()
                except Exception as e:
                    logger.error(e)
                    transaction.savepoint_rollback(save_id)
                    return Response({'error': '调配失败,请联系管理员'}, status=status.HTTP_400_BAD_REQUEST)
                transaction.savepoint_commit(save_id)
        return Response({'success': '调配成功'}, status=status.HTTP_200_OK)


class CashActivityWhiteTableModelViewSet(ModelViewSet):

    pagination_class = MyPage
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)
    search_fields = ('mobile', 'business_no')
    filter_class = CashActivityWhiteTableFilter
    serializer_class = CashActivityWhiteTableModelSerializer

    def get_queryset(self):
        user = self.request.iser
        level = user.level
        level_id = self.request.query_params.get('level', None)
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        if level.level == 0:
            queryset = CashActivityWhiteTable.objects.all()
        elif level.level == 1:
            queryset = CashActivityWhiteTable.objects.filter(Q(level__prov_id=level.id) | Q(is_admin=1))
        elif level.level == 2:
            queryset = CashActivityWhiteTable.objects.filter(Q(level__city_id=level.id) | Q(is_admin=1))
        elif level.level == 3:
            queryset = CashActivityWhiteTable.objects.filter(Q(level__district_id=level.id) | Q(is_admin=1))
        else:
            queryset = CashActivityWhiteTable.objects.filter(Q(level__branch_id=level.id) | Q(is_admin=1))
        # queryset = CashActivityWhiteTable.objects.filter()
        return queryset.order_by('-id')

    def export_cashactivitywhitetable(self, request):
        user = self.request.iser
        cashactivity_id = self.request.query_params.get('cashactivity_id', None)
        level_id = self.request.query_params.get('level_id', None)
        is_admin = self.request.query_params.get('is_admin', None)
        search = self.request.query_params.get('search', None)
        level = user.level
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        if level.level == 0:
            condition = 'WHERE id != 0'
        elif level.level == 1:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE prov_id={level.id}) OR is_admin=1'
        elif level.level == 2:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE city_id={level.id}) OR is_admin=1'
        elif level.level == 3:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE district_id={level.id}) OR is_admin=1'
        else:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE branch_id={level.id}) OR is_admin=1'
        if search:
            condition = condition + f' AND (mobile LIKE "%{search}%" OR business_no LIKE "%{search}%")'
        if cashactivity_id:
            condition = condition + f' AND cashactivity_id in ({cashactivity_id})'
        if is_admin:
            condition = condition + f' AND is_admin in ({is_admin})'
        conn = pymysql.connect(host=settings.DATABASES['default']['HOST'],
                               port=settings.DATABASES['default']['PORT'],
                               database=settings.DATABASES['default']['NAME'],
                               user=settings.DATABASES['default']['USER'],
                               password=settings.DATABASES['default']['PASSWORD'])
        cursor = conn.cursor(cursor=pymysql.cursors.SSDictCursor)
        try:
            sql = f'''SELECT e.*,f.nickname FROM (SELECT c.*, d.city_name,district_name,branch_name FROM (SELECT * FROM (SELECT id,mobile,is_admin,add_user_id,DATE_FORMAT(add_time,'%Y-%m-%d %H:%i:%S')AS add_time,business_no FROM tb_cash_activity_white_table {condition})AS a LEFT JOIN (SELECT wyfMerchantID,`name`AS merchant_name,managerName,managermobile,level_id FROM tb_merchant)AS b ON a.business_no=b.wyfMerchantID)AS c LEFT JOIN (SELECT id,city_name,district_name,branch_name FROM tb_u_level)AS d ON c.level_id=d.id)AS e LEFT JOIN (SELECT id,nickname FROM tb_u_user)AS f ON e.add_user_id=f.id;'''
            cursor.execute(sql)
        except:
            sql = f'''SELECT e.*,f.nickname FROM (SELECT c.*, d.city_name,district_name,branch_name FROM (SELECT * FROM (SELECT id,mobile,is_admin,add_user_id,DATE_FORMAT(add_time,'%Y-%m-%d %H:%i:%S')AS add_time,business_no FROM tb_cash_activity_white_table)AS a LEFT JOIN (SELECT wyfMerchantID,`name`AS merchant_name,managerName,managermobile,level_id FROM tb_merchant)AS b ON a.business_no=b.wyfMerchantID)AS c LEFT JOIN (SELECT id,city_name,district_name,branch_name FROM tb_u_level)AS d ON c.level_id=d.id)AS e LEFT JOIN (SELECT id,nickname FROM tb_u_user)AS f ON e.add_user_id=f.id;'''
            cursor.execute(sql)
        ziduan = ['ID', '创建人', '创建时间', '白名单商户号', '白名单手机号', '商户名称', '负责人姓名', '负责人手机号', '所属市公司', '所属区县', '所属网点']
        cols = ['id', 'nickname', 'add_time', 'business_no', 'mobile', 'merchant_name', 'managerName', 'managermobile', 'city_name', 'district_name', 'branch_name']
        response = StreamingHttpResponse(self.get_cashactivitywhitetable_fromat(cols, cursor, conn, ziduan))
        response['Content-Type'] = 'application/octet-stream; charset=gbk'
        response['Content-Disposition'] = "attachment; filename*=utf-8''{}".format(escape_uri_path('微邮惠礼包白名单.csv'))
        return response

    def get_cashactivitywhitetable_fromat(self, cols, cursor, conn, ziduan):
        tmp_str = ""
        # 返回文件的每一列列名
        for col in ziduan:
            tmp_str += '"%s",' % (col)
        yield tmp_str.strip(",") + "\n"
        IS_ADMIN_ENUM = {
            1: '超级管理员',
            0: '客户经理'
        }
        while True:
            tmp_str = ""
            row = cursor.fetchone()
            if row is None:
                cursor.close()
                conn.close()
                break
            for col in cols:
                if col == 'nickname':
                    if row['is_admin'] == 1:
                        tmp_str += '"%s",' % ('管理员')
                    else:
                        tmp_str += '"%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
                else:
                    tmp_str += '"%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
            yield tmp_str.strip(',') + "\n"


class CashActivityLevelModelViewSet(ModelViewSet):

    pagination_class = MyPage
    search_fields = ('level__name', )
    filter_class = CashActivityLevelFilter
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)

    def get_queryset(self):
        user = self.request.iser
        level = user.level
        level_id = self.request.query_params.get('level_id', None)
        sort = self.request.query_params.get('sort', '')
        activity_id = self.request.query_params.get('activity_id', None)
        # activity_id = self.request.query_params.get('activity_id', None)
        # if activity_id:
        #     try:
        #         activity = AliDiscountCoupon.objects.get(id=activity_id)
        #         max_number__sum = activity.alidiscountcouponlevel_set.all().aggregate(Sum('max_number'))['max_number__sum']
        #         if max_number__sum:
        #             remain_number = activity.max_number - max_number__sum
        #         else:
        #             remain_number = activity.max_number
        #         if '_mutable' in self.request.data.__dict__:
        #             self.request.data.__dict__['_mutable'] = True
        #         self.request.data['can_remain_number'] = str(remain_number)
        #     except:
        #         pass
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        if level.level == 0:
            queryset = CashActivityLevel.objects.filter()
        elif level.level == 1:
            queryset = CashActivityLevel.objects.filter(level__prov_id=level.id)
        elif level.level == 2:
            queryset = CashActivityLevel.objects.filter(level__city_id=level.id)
        elif level.level == 3:
            queryset = CashActivityLevel.objects.filter(level__district_id=level.id)
        else:
            queryset = CashActivityLevel.objects.filter(level__branch_id=level.id)
        if not activity_id:
            city_list = list(CashActivity.objects.filter(cashactivitylevel__level_id=level.id).values_list('id', flat=True))
            queryset = queryset.filter(cash_activity_id__in=city_list)
        if sort == '0':
            queryset = queryset.order_by('p_max_amount', 'id')
        elif sort == '1':
            queryset = queryset.order_by('-p_max_amount', 'id')
        elif sort == '2':
            queryset = queryset.order_by('p_take_amount', 'id')
        elif sort == '3':
            queryset = queryset.order_by('-p_take_amount', 'id')
        elif sort == '4':
            queryset = queryset.order_by('p_remain_amount', 'id')
        elif sort == '5':
            queryset = queryset.order_by('-p_remain_amount', 'id')
        elif sort == '6':
            queryset = queryset.order_by(F('p_take_amount') - F('p_receive_amount'), 'id')
        elif sort == '7':
            queryset = queryset.order_by(-(F('p_take_amount') - F('p_receive_amount')), 'id')
        elif sort == '8':
            queryset = queryset.order_by('p_receive_amount', 'id')
        elif sort == '9':
            queryset = queryset.order_by('-p_receive_amount', 'id')
        else:
            queryset = queryset.order_by('level__level', 'id')
        return queryset

    def get_serializer_context(self):
        user = self.request.iser
        return {'user': user}

    def get_serializer_class(self):
        if self.action == 'list':
            return CashActivityLevelListModelSerializer
        else:
            return CashActivityLevelRetrieveModelSerializer

    def export_cashactivitylevel(self, obj):
        activity_id = self.request.query_params.get('activity_id', None)
        search = self.request.query_params.get('search', None)
        dimensionality = self.request.query_params.get('dimensionality', '0,1,2,3,4')
        user = self.request.iser
        if not search:
            if user.level.level == 0:
                condition = f'WHERE level IN ({dimensionality})'
            elif user.level.level == 1:
                condition = f'WHERE prov_id={user.level_id} AND level IN ({dimensionality})'
            elif user.level.level == 2:
                condition = f'WHERE city_id={user.level_id} AND level IN ({dimensionality})'
            elif user.level.level == 3:
                condition = f'WHERE district_id={user.level_id} AND level IN ({dimensionality})'
            else:
                condition = f'WHERE branch_id={user.level_id} AND level IN ({dimensionality})'
        else:
            if user.level.level == 0:
                condition = f'WHERE name LIKE "%{search}%" AND level IN ({dimensionality})'
            elif user.level.level == 1:
                condition = f'WHERE prov_id={user.level_id} AND name LIKE "%{search}%" AND level IN ({dimensionality})'
            elif user.level.level == 2:
                condition = f'WHERE city_id={user.level_id} AND name LIKE "%{search}%" AND level IN ({dimensionality})'
            elif user.level.level == 3:
                condition = f'WHERE district_id={user.level_id} AND name LIKE "%{search}%" AND level IN ({dimensionality})'
            else:
                condition = f'WHERE branch_id={user.level_id} AND name LIKE "%{search}%" AND level IN ({dimensionality})'
        if not activity_id:
            condition1 = 'WHERE'
        else:
            condition1 = f'WHERE cash_activity_id="{activity_id}" AND'
        conn = pymysql.connect(host=settings.DATABASES['default']['HOST'],
                               port=settings.DATABASES['default']['PORT'],
                               database=settings.DATABASES['default']['NAME'],
                               user=settings.DATABASES['default']['USER'],
                               password=settings.DATABASES['default']['PASSWORD'])
        cursor = conn.cursor(cursor=pymysql.cursors.SSDictCursor)
        sql = f'''
            SELECT c.*,d.name,account,prov_name,city_name,district_name,branch_name FROM (SELECT a.*,b.activity_name FROM (SELECT id,level_id,cash_activity_id,p_max_amount,p_take_amount,p_remain_amount,remain_amount,max_amount,(p_take_amount-p_receive_amount)AS p_unclaimed_amount,p_receive_amount FROM tb_cash_activity_level {condition1} level_id IN (SELECT id FROM tb_u_level {condition}))AS a LEFT JOIN (SELECT id,name AS activity_name FROM tb_cash_activity)AS b ON a.cash_activity_id=b.id)AS c LEFT JOIN (SELECT id,name,account,prov_name,city_name,district_name,branch_name FROM tb_u_level)AS d ON c.level_id=d.id;
            '''
        cursor.execute(sql)
        ziduan = ['id', '活动名称', '机构名称', '机构号', '省', '市', '区县', '网点', '活动预算', '已派发额度', '剩余预算', '待领取', '已领取', '分得预算', '剩余可派发额度']
        cols = ['id', 'activity_name', 'name', 'account', 'prov_name', 'city_name', 'district_name', 'branch_name', 'p_max_amount', 'p_take_amount', 'p_remain_amount', 'p_unclaimed_amount', 'p_receive_amount', 'max_amount', 'remain_amount']
        response = StreamingHttpResponse(self.get_cashactivitylevel_fromat(cols, cursor, conn, ziduan))
        response['Content-Type'] = 'application/octet-stream; charset=gbk'
        response['Content-Disposition'] = "attachment; filename*=utf-8''{}".format(escape_uri_path('微信礼包机构分配明细.csv'))
        return response

    def get_cashactivitylevel_fromat(self, cols, cursor, conn, ziduan):
        tmp_str = ""
        # 返回文件的每一列列名
        for col in ziduan:
            tmp_str += '"%s",' % (col)
        yield tmp_str.strip(",") + "\n"
        while True:
            tmp_str = ""
            row = cursor.fetchone()
            if row is None:
                cursor.close()
                conn.close()
                break
            for col in cols:
                # if col == 'unclaimed_number':
                #     tmp_str += '"%s",' % (row['take_number']-row['receive_number'])
                # elif col == 'wait_number':
                #     tmp_str += '"%s",' % (row['receive_number']-row['use_number'])
                if col in ['p_max_amount', 'p_take_amount', 'p_remain_amount', 'p_unclaimed_amount', 'p_receive_amount', 'max_amount', 'remain_amount']:
                    tmp_str += '"%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else 0)
                else:
                    tmp_str += '"%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
            yield tmp_str.strip(',') + "\n"

    def batch_update_max_amount(self, request):
        data_array = self.request.data.get('data_array', None)
        if not data_array:
            return Response({'error': '缺少必传参数'}, status=status.HTTP_400_BAD_REQUEST)
        if not isinstance(data_array, list):
            return Response({'error': '参数格式有误'}, status=status.HTTP_400_BAD_REQUEST)
        with transaction.atomic():
            # 创建事务保存点
            save_id = transaction.savepoint()

            # 暴力回滚
            try:
                for data in data_array:
                    instance = CashActivityLevel.objects.get(id=data['id'])
                    amount = -Decimal(data['amount'])
                    if amount < 0 and instance.remain_amount < abs(amount):
                        transaction.savepoint_rollback(save_id)
                        return Response({'error': f'{instance.id}剩余数量不足扣减'}, status=status.HTTP_400_BAD_REQUEST)
                    cash_activity = instance.cash_activity
                    instance.max_amount = instance.max_amount + amount
                    instance.remain_amount = instance.remain_amount + amount
                    instance.p_max_amount = instance.p_max_amount + amount
                    instance.p_remain_amount = instance.p_remain_amount + amount
                    instance.save()
                    cash_activity.max_amount += amount
                    cash_activity.remain_amount += amount
                    cash_activity.save()
                    relation_set = instance.child_set.all()
                    for relation in relation_set:
                        parent = relation.parent
                        parent.p_max_amount += amount
                        parent.p_remain_amount += amount
                        parent.save()
            except Exception as e:
                logger.error(e)
                # 事务回滚
                transaction.savepoint_rollback(save_id)
                return Response({'error': '修改失败'}, status=status.HTTP_400_BAD_REQUEST)
        transaction.savepoint_commit(save_id)
        return Response({'success': '操作成功'}, status=status.HTTP_200_OK)

    def update(self, request, *args, **kwargs):
        user = self.request.iser
        instance = self.get_object()
        max_amount = self.request.data.get('max_amount', None)
        try:
            max_amount = Decimal(max_amount)
        except:
            return Response({'error': '请输入整数额度'}, status=status.HTTP_400_BAD_REQUEST)
        if instance.cash_activity.activity_state == 4:
            return Response({'error': '已结束活动不可操作'}, status=status.HTTP_400_BAD_REQUEST)
        p_instance = CashActivityLevel.objects.filter(level_id=user.level_id, cash_activity_id=instance.cash_activity_id).first()
        # if instance.max_amount <= 0:
        #     return Response({'error': '机构活动额度不足'}, status=status.HTTP_400_BAD_REQUEST)
        instance_id = instance.id
        p_instance_id = p_instance.id
        if p_instance == instance:
            return Response({'error': '您无权限操作此层级'}, status=status.HTTP_400_BAD_REQUEST)
        with transaction.atomic():
            # 创建事务保存点
            save_id = transaction.savepoint()
            try:
                while True:
                    instance = CashActivityLevel.objects.get(id=instance_id)
                    p_instance = CashActivityLevel.objects.get(id=p_instance_id)
                    amount = max_amount - instance.max_amount
                    if amount > 0:
                        remain_amount = p_instance.remain_amount
                        max_amount = p_instance.max_amount
                        if remain_amount < amount:
                            transaction.savepoint_rollback(save_id)
                            return Response({'error': '活动额度不足'}, status=status.HTTP_400_BAD_REQUEST)
                        operation_type = 3
                        p_operation_type = 4
                        amount1 = amount
                        remark = f'机构管理员通过后台分配:从{p_instance.level.name}获得'
                        p_remark = f'机构管理员通过后台分配:分配给{instance.level.name}'
                    else:
                        if instance.remain_amount < -amount:
                            return Response({'error': '机构活动额度不足'}, status=status.HTTP_400_BAD_REQUEST)
                        operation_type = 4
                        p_operation_type = 3
                        amount1 = -amount
                        remark = f'机构管理员通过后台分配:被{p_instance.level.name}回收'
                        p_remark = f'机构管理员通过后台分配:从{instance.level.name}扣回'
                    origin_remain_amount = instance.remain_amount
                    origin_max_amount = instance.max_amount
                    origin_p_remain_amount = instance.p_remain_amount
                    origin_p_max_amount = instance.p_max_amount
                    new_remain_amount = origin_remain_amount + amount
                    new_max_amount = origin_max_amount + amount
                    new_p_remain_amount = origin_p_remain_amount + amount
                    new_p_max_amount = origin_p_max_amount + amount
                    if new_max_amount == Decimal(0):
                        is_auth = 0
                    else:
                        is_auth = 1
                    result = CashActivityLevel.objects.filter(id=instance_id, remain_amount=origin_remain_amount).update(
                        max_amount=new_max_amount,
                        remain_amount=new_remain_amount,
                        p_max_amount=new_p_max_amount,
                        p_remain_amount=new_p_remain_amount,
                        is_auth=is_auth
                    )
                    if result == 0:
                        continue
                    break
                while True:
                    p_instance = CashActivityLevel.objects.get(id=p_instance_id)
                    p_origin_remain_amount = p_instance.remain_amount
                    p_origin_max_amount = p_instance.max_amount
                    p_new_remain_amount = p_origin_remain_amount - amount
                    p_new_max_amount = p_origin_max_amount - amount
                    result1 = CashActivityLevel.objects.filter(id=p_instance_id, remain_amount=p_origin_remain_amount).update(
                        max_amount=p_new_max_amount,
                        remain_amount=p_new_remain_amount
                    )
                    if result1 == 0:
                        continue
                    break
                try:
                    cashactivitylevelrecord_data = {}
                    cashactivitylevelrecord_data['activity_level_id'] = instance.id
                    cashactivitylevelrecord_data['amount'] = amount1
                    cashactivitylevelrecord_data['operation_type'] = operation_type
                    cashactivitylevelrecord_data['remain_amount'] = new_remain_amount
                    cashactivitylevelrecord_data['p_remain_amount'] = new_p_remain_amount
                    cashactivitylevelrecord_data['max_amount'] = new_max_amount
                    cashactivitylevelrecord_data['p_max_amount'] = new_p_max_amount
                    cashactivitylevelrecord_data['user_id'] = user.id
                    cashactivitylevelrecord_data['remark'] = remark
                    cashactivitylevelrecord_data['activity_id'] = instance.cash_activity_id
                    CashActivityLevelRecord.objects.create(**cashactivitylevelrecord_data)
                    cashactivitylevelrecord_data = {}
                    cashactivitylevelrecord_data['activity_level_id'] = p_instance.id
                    cashactivitylevelrecord_data['amount'] = amount1
                    cashactivitylevelrecord_data['operation_type'] = p_operation_type
                    cashactivitylevelrecord_data['remain_amount'] = p_new_remain_amount
                    cashactivitylevelrecord_data['p_remain_amount'] = p_instance.p_remain_amount
                    cashactivitylevelrecord_data['max_amount'] = p_new_max_amount
                    cashactivitylevelrecord_data['p_max_amount'] = p_instance.p_max_amount
                    cashactivitylevelrecord_data['user_id'] = user.id
                    cashactivitylevelrecord_data['remark'] = p_remark
                    cashactivitylevelrecord_data['activity_id'] = p_instance.cash_activity_id
                    CashActivityLevelRecord.objects.create(**cashactivitylevelrecord_data)
                except Exception as e:
                    print(e)
                    pass
                relation_set = instance.child_set.all()
                for relation in relation_set:
                    parent = relation.parent
                    if p_instance.level.level < parent.level.level:
                        parent.p_max_amount += amount
                        parent.p_remain_amount += amount
                        parent.save()
            except Exception as e:
                logger.error(e)
                transaction.savepoint_rollback(save_id)
                return Response({'error': '调配失败,请联系管理员'}, status=status.HTTP_400_BAD_REQUEST)
            transaction.savepoint_commit(save_id)
            return Response({'success': '调配成功'}, status=status.HTTP_200_OK)

    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        if instance.p_take_amount != 0:
            return Response({'error': '已派发额度,不可删除'}, status=status.HTTP_400_BAD_REQUEST)
        relation_set = instance.child_set.all()
        for relation in relation_set:
            parent = relation.parent
            parent.p_max_amount -= instance.max_amount
            parent.save()
            if parent.p_max_amount == Decimal(0):
                parent.delete()
        relation_set = instance.parent_set.all()
        for relation in relation_set:
            relation.delete()
            child = relation.child
            child.delete()
        instance.delete()
        return Response({'success': '撤销成功'}, status=status.HTTP_200_OK)

    def cash_distributed_statistical(self, request):
        cash_activity_id = self.request.query_params.get('cash_activity_id', None)
        if not cash_activity_id:
            return Response({'error': '缺少必传参数'}, status=status.HTTP_400_BAD_REQUEST)
        instance = self.get_queryset().filter(cash_activity_id=cash_activity_id).order_by('level__level').first()
        if not instance:
            return Response({'error': '无效活动id'}, status=status.HTTP_400_BAD_REQUEST)
        serializer = CashActivityLevelStatisticalModelSerializer(instance)
        return Response({"statisticsData": serializer.data, 'date_now': datetime.datetime.now().strftime('%Y年%m月%d日')}, status=status.HTTP_200_OK)

    def cashactivitylevel_tree(self, requset):
        user = self.request.iser
        cash_activity_id = self.request.query_params.get('cash_activity_id', None)
        if not cash_activity_id:
            return Response({'error': '缺少必传参数'}, status=status.HTTP_400_BAD_REQUEST)
        instance = self.get_queryset().filter(cash_activity_id=cash_activity_id).order_by('level__level').first()
        if not instance:
            return Response({'error': '无效活动id'}, status=status.HTTP_400_BAD_REQUEST)
        serializer = CashActivityLevelTreeModelSerializer(instance, context={'user': user})
        return Response(serializer.data, status=status.HTTP_200_OK)


class CashActivityDataModelViewSet(ModelViewSet):

    pagination_class = MyPage
    filter_class = CashActivityDataFilter
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)
    search_fields = ('customer_user__mobile', )

    def get_queryset(self):
        user = self.request.iser
        level = user.level
        level_id = self.request.query_params.get('level', None)
        cash_activity_level_id = self.request.query_params.get('cash_activity_level_id', None)
        activity_id = self.request.query_params.get('activity_id', None)
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        try:
            if '_mutable' in self.request.data.__dict__:
                self.request.data.__dict__['_mutable'] = True
        except:
            pass
        if level.level == 0:
            queryset = CashActivityData.objects.all().order_by('-id')
        elif level.level == 1:
            queryset = CashActivityData.objects.filter(level__prov_id=level.id).order_by('-id')
        elif level.level == 2:
            queryset = CashActivityData.objects.filter(level__city_id=level.id).order_by('-id')
        elif level.level == 3:
            queryset = CashActivityData.objects.filter(level__district_id=level.id).order_by('-id')
        else:
            queryset = CashActivityData.objects.filter(level__branch_id=level.id).order_by('-id')
        if not cash_activity_level_id and not activity_id:
            city_list = list(CashActivity.objects.filter(cashactivitylevel__level_id=level.id).values_list('id', flat=True))
            queryset = queryset.filter(cash_activity_id__in=city_list)
        if cash_activity_level_id:
            try:
                activity_level = CashActivityLevel.objects.get(id=cash_activity_level_id)
                self.request.data['acitivty_info'] = CashActivityLevelListModelSerializer(activity_level).data
                relation_set = list(activity_level.parent_set.all().values_list('child_id', flat=True))
                relation_set.append(cash_activity_level_id)
                queryset = queryset.filter(cash_activity_level_id__in=relation_set)
            except:
                self.request.data['acitivty_info'] = {}
            # try:
            #     cash_activity_level = CashActivityLevel.objects.get(id=cash_activity_level_id)
            #     queryset = queryset.filter(cash_activity_id=cash_activity_level.cash_activity_id)
            # except:
            #     queryset = queryset.filter(cash_activity_level_id=cash_activity_level_id)
        return queryset

    def get_serializer_class(self):
        if self.action == 'list':
            return CashActivityDataListModelSerializer
        else:
            return CashActivityDataRetrieveModelSerializer

    def export_cashactivitydata(self, request):
        user = self.request.iser
        activity_id = self.request.query_params.get('activity_id', None)
        cash_activity_level_id = self.request.query_params.get('cash_activity_level_id', None)
        level_id = self.request.query_params.get('level_id', None)
        state = self.request.query_params.get('state', None)
        search = self.request.query_params.get('search', None)
        create_time_begin = self.request.query_params.get('create_time_begin', None)
        create_time_end = self.request.query_params.get('create_time_end', None)
        level = user.level
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        if level.level == 0:
            condition = 'WHERE id != 1'
        elif level.level == 1:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE prov_id={level.id})'
        elif level.level == 2:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE city_id={level.id})'
        elif level.level == 3:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE district_id={level.id})'
        else:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE branch_id={level.id})'
        if search:
            condition = condition + f' AND customer_user_id IN (SELECT id FROM tb_u_customer_user WHERE mobile LIKE "%{search}%")'
        if activity_id:
            condition = condition + f' AND cash_activity_id in ({activity_id})'
        if state:
            condition = condition + f' AND state in ({state})'
        if create_time_begin:
            condition = condition + f' AND create_time >= "{create_time_begin + " 00:00:00"}"'
        if create_time_end:
            condition = condition + f' AND create_time <= "{create_time_end + " 23:59:59"}"'
        if cash_activity_level_id:
            activity_level = CashActivityLevel.objects.get(id=cash_activity_level_id)
            relation_set = list(activity_level.parent_set.all().values_list('child_id', flat=True))
            relation_set.append(cash_activity_level_id)
            if len(relation_set) == 1:
                condition = condition + f' AND cash_activity_level_id IN {str(tuple(relation_set)).replace(",", "")}'
            else:
                condition = condition + f' AND cash_activity_level_id IN {tuple(relation_set)}'
        if not activity_id and not cash_activity_level_id:
            city_list = tuple(CashActivity.objects.filter(cashactivitylevel__level_id=level.id).values_list('id', flat=True))
            if len(city_list) == 1:
                city_list = str(city_list).replace(',', '')
            condition = condition + f' AND cash_activity_id in {city_list}'
        conn = pymysql.connect(host=settings.DATABASES['default']['HOST'],
                               port=settings.DATABASES['default']['PORT'],
                               database=settings.DATABASES['default']['NAME'],
                               user=settings.DATABASES['default']['USER'],
                               password=settings.DATABASES['default']['PASSWORD'])
        cursor = conn.cursor(cursor=pymysql.cursors.SSDictCursor)
        try:
            cashactivity = CashActivity.objects.get(id=activity_id)
        except:
            sql = f'''
            SELECT k.*,l.mchid,mchid_name FROM (SELECT i.*,j.activity_name FROM (SELECT g.*, h.account,branch_name,city_name,district_name,account_nine FROM (SELECT e.*, f.companyuser_account,companyuser_banch FROM (SELECT c.*,d.idcode,realname,openid FROM (SELECT a.*,b.companyuser_level_id,companyuser_mobile,companyuser_name FROM (SELECT id,cash_activity_id,amount,state,DATE_FORMAT(create_time,'%Y-%m-%d %H:%i:%S')AS create_time,DATE_FORMAT(received_time,'%Y-%m-%d %H:%i:%S')AS received_time,DATE_FORMAT(expired_time,'%Y-%m-%d %H:%i:%S')AS expired_time,customer_user_id,companyuser_id,payment_no,return_msg,level_id,mobile,channel_id FROM tb_cash_activity_data WHERE id=1)AS a LEFT JOIN (SELECT id,nickname AS companyuser_name,mobile AS companyuser_mobile,level_id AS companyuser_level_id FROM tb_u_user)AS b ON a.companyuser_id=b.id)AS c LEFT JOIN (SELECT id,realname,idcode,new_openid AS openid FROM tb_u_customer_user)AS d ON c.customer_user_id=d.id)AS e LEFT JOIN (SELECT id,name AS companyuser_banch,account AS companyuser_account FROM tb_u_level)AS f ON e.companyuser_level_id=f.id)AS g LEFT JOIN (SELECT id,name AS branch_name,account,city_name,district_name,account_nine FROM tb_u_level)AS h ON g.level_id=h.id)AS i LEFT JOIN (SELECT id,name AS activity_name FROM tb_cash_activity)AS j ON i.cash_activity_id=j.id)AS k LEFT JOIN (SELECT id,mchid,name AS mchid_name FROM tb_channel)AS l ON k.channel_id=l.id;
            '''
            cursor.execute(sql)
            ziduan = ['ID', '活动名称', '活动id', '所属市公司', '所属区县', '所属网点', '领取金额', '领取状态', '派发时间', '领取时间', '撤销时间', '用户openid',
                      '领取人姓名', '领取人手机号',
                      '领取人身份证', '派发员工', '派发员工手机号', '派发员工所属网点', '派发员工网点机构号', '领取渠道', '派发服务商号', '派发流水号', '失败原因', '机构号']
            cols = ['id', 'activity_name', 'cash_activity_id', 'city_name', 'district_name', 'branch_name', 'amount',
                    'state', 'create_time', 'received_time', 'expired_time', 'openid', 'realname', 'mobile', 'idcode',
                    'companyuser_name', 'companyuser_mobile', 'companyuser_banch', 'companyuser_account', 'mchid_name',
                    'mchid', 'payment_no', 'return_msg', 'account_nine']
            response = StreamingHttpResponse(self.get_cashactivitydata_fromat(cols, cursor, conn, ziduan))
            response['Content-Type'] = 'application/octet-stream; charset=gbk'
            response['Content-Disposition'] = "attachment; filename*=utf-8''{}".format(escape_uri_path('微邮惠礼包派发数据.csv'))
            return response
        if cashactivity.is_merchant == 1:
            try:
                sql = f'''
                SELECT q.*,r.merchant_level_name FROM (SELECT * FROM (SELECT * FROM (SELECT k.*,l.mchid,mchid_name FROM (SELECT i.*,j.activity_name FROM (SELECT g.*, h.account,branch_name,city_name,district_name,account_nine FROM (SELECT e.*, f.companyuser_account,companyuser_banch FROM (SELECT c.*,d.idcode,realname,openid FROM (SELECT a.*,b.companyuser_level_id,companyuser_mobile,companyuser_name FROM (SELECT id,cash_activity_id,amount,state,DATE_FORMAT(create_time,'%Y-%m-%d %H:%i:%S')AS create_time,DATE_FORMAT(received_time,'%Y-%m-%d %H:%i:%S')AS received_time,DATE_FORMAT(expired_time,'%Y-%m-%d %H:%i:%S')AS expired_time,customer_user_id,companyuser_id,payment_no,return_msg,level_id,mobile,channel_id FROM tb_cash_activity_data {condition})AS a LEFT JOIN (SELECT id,nickname AS companyuser_name,mobile AS companyuser_mobile,level_id AS companyuser_level_id FROM tb_u_user)AS b ON a.companyuser_id=b.id)AS c LEFT JOIN (SELECT id,realname,idcode,new_openid AS openid FROM tb_u_customer_user)AS d ON c.customer_user_id=d.id)AS e LEFT JOIN (SELECT id,name AS companyuser_banch,account AS companyuser_account FROM tb_u_level)AS f ON e.companyuser_level_id=f.id)AS g LEFT JOIN (SELECT id,name AS branch_name,account,city_name,district_name,account_nine FROM tb_u_level)AS h ON g.level_id=h.id)AS i LEFT JOIN (SELECT id,name AS activity_name FROM tb_cash_activity)AS j ON i.cash_activity_id=j.id)AS k LEFT JOIN (SELECT id,mchid,name AS mchid_name FROM tb_channel)AS l ON k.channel_id=l.id)AS m LEFT JOIN (SELECT activitydata_id,business_no,is_white_table FROM tb_cash_activity_data_white_table)AS n ON m.id=n.activitydata_id)AS o LEFT JOIN (SELECT wyfMerchantID,`name` AS merchant_name,level_id AS merchant_level_id FROM tb_merchant)AS p ON o.business_no=p.wyfMerchantID)AS q LEFT JOIN (SELECT id,`name`AS merchant_level_name FROM tb_u_level)AS r ON q.merchant_level_id=r.id;
                '''
                cursor.execute(sql)
            except:
                sql = f'''
                SELECT q.*,r.merchant_level_name FROM (SELECT * FROM (SELECT * FROM (SELECT k.*,l.mchid,mchid_name FROM (SELECT i.*,j.activity_name FROM (SELECT g.*, h.account,branch_name,city_name,district_name,account_nine FROM (SELECT e.*, f.companyuser_account,companyuser_banch FROM (SELECT c.*,d.idcode,realname,openid FROM (SELECT a.*,b.companyuser_level_id,companyuser_mobile,companyuser_name FROM (SELECT id,cash_activity_id,amount,state,DATE_FORMAT(create_time,'%Y-%m-%d %H:%i:%S')AS create_time,DATE_FORMAT(received_time,'%Y-%m-%d %H:%i:%S')AS received_time,DATE_FORMAT(expired_time,'%Y-%m-%d %H:%i:%S')AS expired_time,customer_user_id,companyuser_id,payment_no,return_msg,level_id,mobile,channel_id FROM tb_cash_activity_data WHERE id=1)AS a LEFT JOIN (SELECT id,nickname AS companyuser_name,mobile AS companyuser_mobile,level_id AS companyuser_level_id FROM tb_u_user)AS b ON a.companyuser_id=b.id)AS c LEFT JOIN (SELECT id,realname,idcode,new_openid AS openid FROM tb_u_customer_user)AS d ON c.customer_user_id=d.id)AS e LEFT JOIN (SELECT id,name AS companyuser_banch,account AS companyuser_account FROM tb_u_level)AS f ON e.companyuser_level_id=f.id)AS g LEFT JOIN (SELECT id,name AS branch_name,account,city_name,district_name,account_nine FROM tb_u_level)AS h ON g.level_id=h.id)AS i LEFT JOIN (SELECT id,name AS activity_name FROM tb_cash_activity)AS j ON i.cash_activity_id=j.id)AS k LEFT JOIN (SELECT id,mchid,name AS mchid_name FROM tb_channel)AS l ON k.channel_id=l.id)AS m LEFT JOIN (SELECT activitydata_id,business_no,is_white_table FROM tb_cash_activity_data_white_table)AS n ON m.id=n.activitydata_id)AS o LEFT JOIN (SELECT wyfMerchantID,`name` AS merchant_name,level_id AS merchant_level_id FROM tb_merchant)AS p ON o.business_no=p.wyfMerchantID)AS q LEFT JOIN (SELECT id,`name`AS merchant_level_name FROM tb_u_level)AS r ON q.merchant_level_id=r.id;
                '''
                cursor.execute(sql)
            ziduan = ['ID', '活动名称', '活动id', '所属市公司', '所属区县', '所属网点', '领取金额', '领取状态', '派发时间', '领取时间', '撤销时间', '用户openid',
                      '领取人姓名', '领取人手机号',
                      '领取人身份证', '派发员工', '派发员工手机号', '派发员工所属网点', '派发员工网点机构号', '领取渠道', '派发服务商号', '派发流水号', '失败原因', '机构号',
                      '微邮付商户号', '商户名称', '商户归属', '是否通过白名单参与']
            cols = ['id', 'activity_name', 'cash_activity_id', 'city_name', 'district_name', 'branch_name', 'amount',
                    'state', 'create_time', 'received_time', 'expired_time', 'openid', 'realname', 'mobile', 'idcode',
                    'companyuser_name', 'companyuser_mobile', 'companyuser_banch', 'companyuser_account', 'mchid_name',
                    'mchid', 'payment_no', 'return_msg', 'account_nine', 'business_no', 'merchant_name', 'merchant_level_name', 'is_white_table']
            response = StreamingHttpResponse(self.get_cashactivitydata_fromat(cols, cursor, conn, ziduan))
            response['Content-Type'] = 'application/octet-stream; charset=gbk'
            response['Content-Disposition'] = "attachment; filename*=utf-8''{}".format(escape_uri_path('微邮惠礼包派发数据.csv'))
            return response
        else:
            try:
                sql = f'''
                SELECT k.*,l.mchid,mchid_name FROM (SELECT i.*,j.activity_name FROM (SELECT g.*, h.account,branch_name,city_name,district_name,account_nine FROM (SELECT e.*, f.companyuser_account,companyuser_banch FROM (SELECT c.*,d.idcode,realname,openid FROM (SELECT a.*,b.companyuser_level_id,companyuser_mobile,companyuser_name FROM (SELECT id,cash_activity_id,amount,state,DATE_FORMAT(create_time,'%Y-%m-%d %H:%i:%S')AS create_time,DATE_FORMAT(received_time,'%Y-%m-%d %H:%i:%S')AS received_time,DATE_FORMAT(expired_time,'%Y-%m-%d %H:%i:%S')AS expired_time,customer_user_id,companyuser_id,payment_no,return_msg,level_id,mobile,channel_id FROM tb_cash_activity_data {condition})AS a LEFT JOIN (SELECT id,nickname AS companyuser_name,mobile AS companyuser_mobile,level_id AS companyuser_level_id FROM tb_u_user)AS b ON a.companyuser_id=b.id)AS c LEFT JOIN (SELECT id,realname,idcode,new_openid AS openid FROM tb_u_customer_user)AS d ON c.customer_user_id=d.id)AS e LEFT JOIN (SELECT id,name AS companyuser_banch,account AS companyuser_account FROM tb_u_level)AS f ON e.companyuser_level_id=f.id)AS g LEFT JOIN (SELECT id,name AS branch_name,account,city_name,district_name,account_nine FROM tb_u_level)AS h ON g.level_id=h.id)AS i LEFT JOIN (SELECT id,name AS activity_name FROM tb_cash_activity)AS j ON i.cash_activity_id=j.id)AS k LEFT JOIN (SELECT id,mchid,name AS mchid_name FROM tb_channel)AS l ON k.channel_id=l.id;
                '''
                cursor.execute(sql)
            except:
                sql = f'''
                SELECT k.*,l.mchid,mchid_name FROM (SELECT i.*,j.activity_name FROM (SELECT g.*, h.account,branch_name,city_name,district_name,account_nine FROM (SELECT e.*, f.companyuser_account,companyuser_banch FROM (SELECT c.*,d.idcode,realname,openid FROM (SELECT a.*,b.companyuser_level_id,companyuser_mobile,companyuser_name FROM (SELECT id,cash_activity_id,amount,state,DATE_FORMAT(create_time,'%Y-%m-%d %H:%i:%S')AS create_time,DATE_FORMAT(received_time,'%Y-%m-%d %H:%i:%S')AS received_time,DATE_FORMAT(expired_time,'%Y-%m-%d %H:%i:%S')AS expired_time,customer_user_id,companyuser_id,payment_no,return_msg,level_id,mobile,channel_id FROM tb_cash_activity_data WHERE id=1)AS a LEFT JOIN (SELECT id,nickname AS companyuser_name,mobile AS companyuser_mobile,level_id AS companyuser_level_id FROM tb_u_user)AS b ON a.companyuser_id=b.id)AS c LEFT JOIN (SELECT id,realname,idcode,new_openid AS openid FROM tb_u_customer_user)AS d ON c.customer_user_id=d.id)AS e LEFT JOIN (SELECT id,name AS companyuser_banch,account AS companyuser_account FROM tb_u_level)AS f ON e.companyuser_level_id=f.id)AS g LEFT JOIN (SELECT id,name AS branch_name,account,city_name,district_name,account_nine FROM tb_u_level)AS h ON g.level_id=h.id)AS i LEFT JOIN (SELECT id,name AS activity_name FROM tb_cash_activity)AS j ON i.cash_activity_id=j.id)AS k LEFT JOIN (SELECT id,mchid,name AS mchid_name FROM tb_channel)AS l ON k.channel_id=l.id;
                '''
                cursor.execute(sql)
            ziduan = ['ID', '活动名称', '活动id', '所属市公司', '所属区县', '所属网点', '领取金额', '领取状态', '派发时间', '领取时间', '撤销时间', '用户openid', '领取人姓名', '领取人手机号',
                      '领取人身份证', '派发员工', '派发员工手机号', '派发员工所属网点', '派发员工网点机构号', '领取渠道', '派发服务商号', '派发流水号', '失败原因', '机构号']
            cols = ['id', 'activity_name', 'cash_activity_id', 'city_name', 'district_name', 'branch_name', 'amount', 'state', 'create_time', 'received_time', 'expired_time', 'openid', 'realname', 'mobile', 'idcode',
                    'companyuser_name', 'companyuser_mobile', 'companyuser_banch', 'companyuser_account', 'mchid_name', 'mchid', 'payment_no', 'return_msg', 'account_nine']
            response = StreamingHttpResponse(self.get_cashactivitydata_fromat(cols, cursor, conn, ziduan))
            response['Content-Type'] = 'application/octet-stream; charset=gbk'
            response['Content-Disposition'] = "attachment; filename*=utf-8''{}".format(escape_uri_path('微邮惠礼包派发数据.csv'))
            return response

    def get_cashactivitydata_fromat(self, cols, cursor, conn, ziduan):
        tmp_str = ""
        # 返回文件的每一列列名
        for col in ziduan:
            tmp_str += '"%s",' % (col)
        yield tmp_str.strip(",") + "\n"
        STATE_ENUM = {
            1: '待领取',
            2: '已领取',
            3: '领取失败',
            4: '已撤销'
        }
        while True:
            tmp_str = ""
            row = cursor.fetchone()
            if row is None:
                cursor.close()
                conn.close()
                break
            for col in cols:
                if col == 'state':
                    tmp_str += '"%s",' % (STATE_ENUM[row[col]])
                elif col == 'is_white_table':
                    if row['is_white_table'] == 1:
                        tmp_str += '"%s",' % ('是')
                    else:
                        tmp_str += '"%s",' % ('否')
                elif col in ['payment_no']:
                    tmp_str += '"\'%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
                elif col in ['idcode']:
                    tmp_str += '"%s",' % ''
                elif col == 'expired_time':
                    tmp_str += '"%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row['state'] == 4 else '')
                else:
                    tmp_str += '"%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
            yield tmp_str.strip(',') + "\n"


class CashActivityLevelRecordModelViewSet(ModelViewSet):

    pagination_class = MyPage
    filter_class = CashActivityLevelRecordFilter
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)
    search_fields = ('user__nickname', )
    serializer_class = CashActivityLevelRecordModelSerializer

    def get_queryset(self):
        user = self.request.iser
        level = user.level
        cash_activity_level_id = self.request.query_params.get('cash_activity_level_id', None)
        activity_id = self.request.query_params.get('activity_id', None)
        queryset = CashActivityLevelRecord.objects.all()
        # if level.level == 0:
        #     queryset = queryset.all()
        # elif level.level == 1:
        #     queryset = queryset.filter(level__prov_id=level.id)
        # elif level.level == 2:
        #     queryset = queryset.filter(level__city_id=level.id)
        # elif level.level == 3:
        #     queryset = queryset.filter(level__district_id=level.id)
        # else:
        #     queryset = queryset.filter(level__branch_id=level.id)
        if not cash_activity_level_id and not activity_id:
            city_list = list(CashActivity.objects.filter(cashactivitylevel__level_id=level.id).values_list('id', flat=True))
            queryset = queryset.filter(activity_id__in=city_list)
        return queryset.order_by('-create_time')


class AliDiscountCouponMerchantModelViewSet(ModelViewSet):

    pagination_class = MyPage
    filter_class = AliDiscountCouponMerchantFilter
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)
    search_fields = ('merchant__name', 'merchant__wyfMerchantID', 'sub_mchid')

    def get_queryset(self):
        user = self.request.iser
        level = user.level
        level_id = self.request.query_params.get('level', None)
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        if level.level == 0:
            queryset = AliDiscountCouponMerchant.objects.all()
        elif level.level == 1:
            queryset = AliDiscountCouponMerchant.objects.filter(merchant__level__prov_id=level.id)
        elif level.level == 2:
            queryset = AliDiscountCouponMerchant.objects.filter(merchant__level__city_id=level.id)
        elif level.level == 3:
            queryset = AliDiscountCouponMerchant.objects.filter(merchant__level__district_id=level.id)
        else:
            queryset = AliDiscountCouponMerchant.objects.filter(merchant__level__branch_id=level.id)
        return queryset

    def get_serializer_class(self):
        return AliDiscountCouponMerchantModelSerializer


class WaivePaymentActivityModelViewSet(ModelViewSet):

    pagination_class = MyPage
    filter_class = WaivePaymentActivityFilter
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)
    search_fields = ('activity_name', )
    serializer_class = WaivePaymentActivityModelSerializer

    def get_serializer_context(self):
        user = self.request.iser
        return {'user': user}

    def get_queryset(self):
        today = datetime.datetime.today()
        user = self.request.iser
        level = user.level
        level_id = self.request.query_params.get('level', None)
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        if level.level == 0:
            queryset = WaivePaymentActivity.objects.all()
        elif level.level == 1:
            queryset = WaivePaymentActivity.objects.filter(waivepaymentmerchant__level__prov_id=level.id)
        elif level.level == 2:
            queryset = WaivePaymentActivity.objects.filter(waivepaymentmerchant__level__city_id=level.id)
        elif level.level == 3:
            queryset = WaivePaymentActivity.objects.filter(waivepaymentmerchant__level__district_id=level.id)
        else:
            queryset = WaivePaymentActivity.objects.filter(waivepaymentmerchant__level__branch_id=level.id)
        # queryset = WaivePaymentActivity.objects.filter(waivepaymentmerchant__level_id=level.id)
        return queryset.filter(available_end_time__gte=today, available_begin_time__lte=today).exclude(id__in=[2,3,4,5,6,7,8,10]).distinct().order_by('-id')


class WaivePaymentAdvanceModelViewSet(ModelViewSet):

    pagination_class = MyPage
    filter_class = WaivePaymentAdvanceFilter
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)
    search_fields = ('name', )
    queryset = WaivePaymentAdvance.objects.all().order_by('-id')
    serializer_class = WaivePaymentAdvanceModelSerializer


class WaivePaymentMerchantModelViewSet(ModelViewSet):

    pagination_class = MyPage
    filter_class = WaivePaymentMerchantFilter
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)
    search_fields = ('waivepaymentactivity__activity_name', 'business_no')

    def get_queryset(self):
        user = self.request.iser
        level = user.level
        level_id = self.request.query_params.get('level', None)
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        if level.level == 0:
            queryset = WaivePaymentMerchant.objects.all()
        elif level.level == 1:
            queryset = WaivePaymentMerchant.objects.filter(level__prov_id=level.id)
        elif level.level == 2:
            queryset = WaivePaymentMerchant.objects.filter(level__city_id=level.id)
        elif level.level == 3:
            queryset = WaivePaymentMerchant.objects.filter(level__district_id=level.id)
        else:
            queryset = WaivePaymentMerchant.objects.filter(level__branch_id=level.id)
        return queryset.exclude(waivepaymentactivity_id__in=[2,3,4,5,6,7,8,10]).order_by('-amount', '-payment_state')

    def get_serializer_class(self):
        if self.action == 'list':
            return WaivePaymentMerchantListModelSerializer
        else:
            return WaivePaymentMerchantRetrieveModelSerializer

    def export_waivepaymentmerchant(self, request):
        user = self.request.iser
        waivepaymentactivity_id = self.request.query_params.get('waivepaymentactivity_id', None)
        waivepaymentadvance_id = self.request.query_params.get('waivepaymentadvance_id', None)
        level_id = self.request.query_params.get('level', None)
        payment_state = self.request.query_params.get('payment_state', None)
        search = self.request.query_params.get('search', None)
        level = user.level
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        if level.level == 0:
            condition = 'WHERE level_id IN (SELECT id FROM tb_u_level) AND waivepaymentactivity_id not in (2,3,4,5,6,7,8,10)'
        elif level.level == 1:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE prov_id={level.id}) AND waivepaymentactivity_id not in (2,3,4,5,6,7,8,10)'
        elif level.level == 2:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE city_id={level.id}) AND waivepaymentactivity_id not in (2,3,4,5,6,7,8,10)'
        elif level.level == 3:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE district_id={level.id}) AND waivepaymentactivity_id not in (2,3,4,5,6,7,8,10)'
        else:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE branch_id={level.id}) AND waivepaymentactivity_id not in (2,3,4,5,6,7,8,10)'
        if search:
            condition = condition + f' AND (merchant_id IN (SELECT id FROM tb_merchant WHERE short_name LIKE "%{search}%" OR wyfMerchantID LIKE "%{search}%"))'
        if payment_state:
            condition = condition + f' AND payment_state in ({payment_state})'
        if waivepaymentadvance_id:
            condition = condition + f' AND waivepaymentadvance_id={waivepaymentadvance_id}'
        if waivepaymentactivity_id:
            condition = condition + f' AND waivepaymentactivity_id={waivepaymentactivity_id}'
        conn = pymysql.connect(host=settings.DATABASES['default']['HOST'],
                               port=settings.DATABASES['default']['PORT'],
                               database=settings.DATABASES['default']['NAME'],
                               user=settings.DATABASES['default']['USER'],
                               password=settings.DATABASES['default']['PASSWORD'])
        cursor = conn.cursor(cursor=pymysql.cursors.SSDictCursor)
        try:
            sql = f'''
            SELECT i.*,j.mobile FROM (SELECT g.*,h.city_name,district_name,branch_name FROM (SELECT e.*,f.waivepaymentmerchant_id,trade_money,trade_type,trade_time,trade_no FROM (SELECT c.*,d.merchant_name,short_name FROM (SELECT a.*,b.activity_name FROM (SELECT id,waivepaymentactivity_id,business_no,merchant_id,merchant_user_id,account,name,payment_no,amount,payment_state,DATE_FORMAT(payment_time,'%Y-%m-%d %H:%i:%S')AS payment_time,company_mobile,return_msg,level_id FROM tb_waive_payment_merchant {condition})AS a LEFT JOIN (SELECT id,activity_name FROM tb_waive_payment_activity)AS b ON a.waivepaymentactivity_id=b.id)AS c LEFT JOIN (SELECT id,name AS merchant_name,short_name FROM tb_merchant)AS d ON c.merchant_id=d.id)AS e LEFT JOIN (SELECT id,waivepaymentmerchant_id,trade_money,trade_type,DATE_FORMAT(trade_time_end,'%Y-%m-%d %H:%i:%S')AS trade_time,trade_no FROM tb_waive_payment_order WHERE is_hit=1)AS f ON e.id=f.waivepaymentmerchant_id)AS g LEFT JOIN (SELECT id,city_name,district_name,branch_name FROM tb_u_level)AS h ON g.level_id=h.id)AS i LEFT JOIN (SELECT id,mobile FROM tb_m_merchant_user)AS j ON i.merchant_user_id=j.id;
            '''
            cursor.execute(sql)
        except:
            sql = f'''
            SELECT i.*,j.mobile FROM (SELECT g.*,h.city_name,district_name,branch_name FROM (SELECT e.*,f.waivepaymentmerchant_id,trade_money,trade_type,trade_time,trade_no FROM (SELECT c.*,d.merchant_name,short_name FROM (SELECT a.*,b.activity_name FROM (SELECT id,waivepaymentactivity_id,business_no,merchant_id,merchant_user_id,account,name,payment_no,amount,payment_state,DATE_FORMAT(payment_time,'%Y-%m-%d %H:%i:%S')AS payment_time,company_mobile,return_msg,level_id FROM tb_waive_payment_merchant)AS a LEFT JOIN (SELECT id,activity_name FROM tb_waive_payment_activity)AS b ON a.waivepaymentactivity_id=b.id)AS c LEFT JOIN (SELECT id,name AS merchant_name,short_name FROM tb_merchant)AS d ON c.merchant_id=d.id)AS e LEFT JOIN (SELECT id,waivepaymentmerchant_id,trade_money,trade_type,DATE_FORMAT(trade_time_end,'%Y-%m-%d %H:%i:%S')AS trade_time,trade_no FROM tb_waive_payment_order WHERE is_hit=1)AS f ON e.id=f.waivepaymentmerchant_id)AS g LEFT JOIN (SELECT id,city_name,district_name,branch_name FROM tb_u_level)AS h ON g.level_id=h.id)AS i LEFT JOIN (SELECT id,mobile FROM tb_m_merchant_user)AS j ON i.merchant_user_id=j.id;
            '''
            cursor.execute(sql)
        ziduan = ['ID', '活动名称', '商户号', '商户全称', '商户简称', '归属市公司', '归属区县', '归属网点',
                  '领取手机号', '领取支付宝账户', '支付宝实名信息', '打款支付宝订单号', '免单订单号', '交易金额', '交易类型', '交易时间', '免单金额',
                  '领取状态', '领取时间', '参与码', '领取失败原因']
        cols = ['id', 'activity_name', 'business_no', 'merchant_name', 'short_name', 'city_name', 'district_name', 'branch_name',
                'mobile', 'account', 'name', 'payment_no', 'trade_no', 'trade_money', 'trade_type', 'trade_time', 'amount', 'payment_state',
                'payment_time', 'company_mobile', 'return_msg']
        response = StreamingHttpResponse(self.get_waivepaymentmerchant_fromat(cols, cursor, conn, ziduan))
        response['Content-Type'] = 'application/octet-stream; charset=gbk'
        response['Content-Disposition'] = "attachment; filename*=utf-8''{}".format(escape_uri_path('月月免单领取明细.csv'))
        return response

    def get_waivepaymentmerchant_fromat(self, cols, cursor, conn, ziduan):
        tmp_str = ""
        # 返回文件的每一列列名
        for col in ziduan:
            tmp_str += '"%s",' % (col)
        yield tmp_str.strip(",") + "\n"
        TRADE_TYPE_ENUM = {
            1: '支付宝',
            2: '微信',
            3: '云闪付'
        }
        PAYMENT_STATE_ENUM = {
            0: '未激活',
            1: '待领取',
            2: '已领取',
            3: '领取失败',
            4: '已撤销',
            5: '待抽奖',
            6: '无效'
        }
        while True:
            tmp_str = ""
            row = cursor.fetchone()
            if row is None:
                cursor.close()
                conn.close()
                break
            for col in cols:
                # if col == 'trade_type':
                #     tmp_str += '"%s",' % (TRADE_TYPE_ENUM[row[col]])
                if col == 'payment_state':
                    tmp_str += '"%s",' % (PAYMENT_STATE_ENUM[row[col]])
                elif col in ['amount', 'trade_no', 'trade_money', 'trade_type', 'trade_time']:
                    if row['payment_state'] in [1, 2, 3, 4, 5, 0]:
                        if col == 'trade_no':
                            tmp_str += '"\'%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
                        elif col == 'trade_type':
                            tmp_str += '"%s",' % (TRADE_TYPE_ENUM[row[col]])
                        else:
                            tmp_str += '"%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
                    else:
                        tmp_str += '"%s",' % ''
                elif col in ['payment_no']:
                    tmp_str += '"\'%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
                else:
                    tmp_str += '"%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
            yield tmp_str.strip(',') + "\n"


class WaivePaymentOrderModelViewSet(ModelViewSet):

    pagination_class = MyPage
    filter_class = WaivePaymentOrderFilter
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)
    search_fields = ('waivepaymentactivity__activity_name', 'business_no')
    # queryset = WaivePaymentOrder.objects.all().order_by('-is_hit')
    serializer_class = WaivePaymentOrderModelSerializer

    def get_queryset(self):
        user = self.request.iser
        level = user.level
        level_id = self.request.query_params.get('level', None)
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        if level.level == 0:
            queryset = WaivePaymentOrder.objects.all()
        elif level.level == 1:
            queryset = WaivePaymentOrder.objects.filter(waivepaymentmerchant__level__prov_id=level.id)
        elif level.level == 2:
            queryset = WaivePaymentOrder.objects.filter(waivepaymentmerchant__level__city_id=level.id)
        elif level.level == 3:
            queryset = WaivePaymentOrder.objects.filter(waivepaymentmerchant__level__district_id=level.id)
        else:
            queryset = WaivePaymentOrder.objects.filter(waivepaymentmerchant__level__branch_id=level.id)
        return queryset.order_by('-is_hit')


class CustomizeActivityModelViewSet(ModelViewSet):

    pagination_class = MyPage
    filter_class = CustomizeActivityFilter
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)
    search_fields = ('activity_name',)

    def get_queryset(self):
        today = datetime.datetime.now()
        user = self.request.iser
        level = user.level
        prize_type = self.request.query_params.get('prize_type', None)
        queryset = CustomizeActivity.objects.filter(customizeactivitylevel__level_id=level.id)
        if prize_type:
            try:
                prize_type = prize_type.split(',')
                if len(prize_type) == 1:
                    queryset = queryset.filter(prize_type__contains=prize_type[0])
                elif len(prize_type) == 2:
                    queryset = queryset.filter(Q(prize_type__contains=prize_type[0]) | Q(prize_type__contains=prize_type[1]))
                elif len(prize_type) == 3:
                    queryset = queryset.filter(Q(prize_type__contains=prize_type[0]) | Q(prize_type__contains=prize_type[1]) | Q(prize_type__contains=prize_type[2]))
            except:
                pass
        return queryset.filter(available_end_time__gte=today, available_begin_time__lte=today).order_by('-id')

    def get_serializer_class(self):
        if self.action == 'list':
            return CustomizeActivityListModelSerializer
        else:
            return CustomizeActivityRetrieveModelSerializer

    def customize_white_table(self, request):
        customizeactivity_id = self.request.query_params.get('customizeactivity_id', None)
        try:
            instance = self.get_queryset().get(id=customizeactivity_id)
        except:
            return Response({'error': '无效活动id'}, status=status.HTTP_400_BAD_REQUEST)
        customizeactivitywhitetable_set = instance.customizeactivitywhitetable_set.all().values_list('mobile', flat=True)
        return Response({'data': list(customizeactivitywhitetable_set)}, status=status.HTTP_200_OK)


class CustomizeActivityFlipCARDSModelViewSet(ModelViewSet):

    pagination_class = MyPage
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)
    search_fields = ('user__mobile', )
    filter_class = CustomizeActivityFlipCARDSFilter

    def get_queryset(self):
        user = self.request.iser
        level_id = self.request.query_params.get('level_id', None)
        level = user.level
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass

        if level.level == 0:
            queryset = CustomizeActivityFlipCARDS.objects.filter(open_status__in=[2, 4, 6]).order_by('-id')
        elif level.level == 1:
            queryset = CustomizeActivityFlipCARDS.objects.filter(level__prov_id=level.id, open_status__in=[2, 4, 6]).order_by('-id')
        elif level.level == 2:
            queryset = CustomizeActivityFlipCARDS.objects.filter(level__city_id=level.id, open_status__in=[2, 4, 6]).order_by('-id')
        elif level.level == 3:
            queryset = CustomizeActivityFlipCARDS.objects.filter(level__district_id=level.id, open_status__in=[2, 4, 6]).order_by('-id')
        else:
            queryset = CustomizeActivityFlipCARDS.objects.filter(level__branch_id=level.id, open_status__in=[2, 4, 6]).order_by('-id')
        # queryset = CustomizeActivityFlipCARDS.objects.filter(level_id=level.id, open_status__in=[2, 4, 6]).order_by('-id')
        return queryset.filter(open_time__gte='2025-04-01 00:00:00')

    def get_serializer_class(self):
        if self.action == 'list':
            return CustomizeActivityFlipCARDSListModelSerializer
        else:
            return CustomizeActivityFlipCARDSRetrieveModelSerializer

    def export_customizeactivityflipcards(self, request):
        user = self.request.iser
        customizeactivity_id = self.request.query_params.get('customizeactivity_id', None)
        level_id = self.request.query_params.get('level_id', None)
        open_status = self.request.query_params.get('open_status', None)
        search = self.request.query_params.get('search', None)
        received_time_begin = self.request.query_params.get('received_time_begin', None)
        received_time_end = self.request.query_params.get('received_time_end', None)
        level = user.level
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        if level.level == 0:
            condition = 'WHERE open_status IN (2,4,6)'
        elif level.level == 1:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE prov_id={level.id}) AND open_status IN (2,4,6)'
        elif level.level == 2:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE city_id={level.id}) AND open_status IN (2,4,6)'
        elif level.level == 3:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE district_id={level.id}) AND open_status IN (2,4,6)'
        else:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE branch_id={level.id}) AND open_status IN (2,4,6)'
        if search:
            condition = condition + f' AND mobile LIKE "%{search}%"'
        if open_status:
            condition = condition + f' AND open_status IN ({open_status})'
        if customizeactivity_id:
            condition = condition + f' AND customizeactivity_id={customizeactivity_id}'
        if received_time_begin:
            condition = condition + f' AND received_time >= "{received_time_begin + " 00:00:00"}"'
        if received_time_end:
            condition = condition + f' AND received_time <= "{received_time_end + " 23:59:59"}"'
        conn = pymysql.connect(host=settings.DATABASES['default']['HOST'],
                               port=settings.DATABASES['default']['PORT'],
                               database=settings.DATABASES['default']['NAME'],
                               user=settings.DATABASES['default']['USER'],
                               password=settings.DATABASES['default']['PASSWORD'])
        cursor = conn.cursor(cursor=pymysql.cursors.SSDictCursor)
        try:
            sql = f'''
            SELECT k.*,l.business_name,business_type,business_amount,business_account FROM (SELECT i.*,j.c_activity_name FROM (SELECT g.*,h.c_amount,mchid FROM (SELECT e.*,f.v_activity_name,v_floor_amount,v_amount FROM (SELECT c.*,d.city_name,district_name,branch_name FROM (SELECT a.*,b.activity_name FROM (SELECT id,open_status,DATE_FORMAT(open_time,'%Y-%m-%d %H:%i:%S')AS open_time,DATE_FORMAT(received_time,'%Y-%m-%d %H:%i:%S')AS received_time,level_id,win_type,alidiscountcoupon_id,cashactivitydata_id,cashactivity_id,mobile,customizeactivity_id FROM tb_customize_activity_flip_cards {condition})AS a LEFT JOIN (SELECT id,activity_name FROM tb_customize_activity)AS b ON a.customizeactivity_id=b.id)AS c LEFT JOIN (SELECT id,city_name,district_name,branch_name FROM tb_u_level)AS d ON c.level_id=d.id)AS e LEFT JOIN (SELECT id,activity_name AS v_activity_name,floor_amount AS v_floor_amount,amount AS v_amount FROM tb_ali_discount_coupon)AS f ON e.alidiscountcoupon_id=f.id)AS g LEFT JOIN (SELECT id,amount AS c_amount,mchid FROM tb_cash_activity_data)AS h ON g.cashactivitydata_id=h.id)AS i LEFT JOIN (SELECT id,name AS c_activity_name FROM tb_cash_activity)AS j ON i.cashactivity_id=j.id)AS k LEFT JOIN (SELECT customizeactivityflipcards_id,business_name,business_type,business_amount,business_account FROM tb_customize_activity_business_form)AS l ON k.id=l.customizeactivityflipcards_id;
            '''
            cursor.execute(sql)
        except:
            sql = f'''
            SELECT k.*,l.business_name,business_type,business_amount,business_account FROM (SELECT i.*,j.c_activity_name FROM (SELECT g.*,h.c_amount,mchid FROM (SELECT e.*,f.v_activity_name,v_floor_amount,v_amount FROM (SELECT c.*,d.city_name,district_name,branch_name FROM (SELECT a.*,b.activity_name FROM (SELECT id,open_status,DATE_FORMAT(open_time,'%Y-%m-%d %H:%i:%S')AS open_time,DATE_FORMAT(received_time,'%Y-%m-%d %H:%i:%S')AS received_time,level_id,win_type,alidiscountcoupon_id,cashactivitydata_id,cashactivity_id,mobile,customizeactivity_id FROM tb_customize_activity_flip_cards)AS a LEFT JOIN (SELECT id,activity_name FROM tb_customize_activity)AS b ON a.customizeactivity_id=b.id)AS c LEFT JOIN (SELECT id,city_name,district_name,branch_name FROM tb_u_level)AS d ON c.level_id=d.id)AS e LEFT JOIN (SELECT id,activity_name AS v_activity_name,floor_amount AS v_floor_amount,amount AS v_amount FROM tb_ali_discount_coupon)AS f ON e.alidiscountcoupon_id=f.id)AS g LEFT JOIN (SELECT id,amount AS c_amount,mchid FROM tb_cash_activity_data)AS h ON g.cashactivitydata_id=h.id)AS i LEFT JOIN (SELECT id,name AS c_activity_name FROM tb_cash_activity)AS j ON i.cashactivity_id=j.id)AS k LEFT JOIN (SELECT customizeactivityflipcards_id,business_name,business_type,business_amount,business_account FROM tb_customize_activity_business_form)AS l ON k.id=l.customizeactivityflipcards_id;
            '''
            cursor.execute(sql)
        ziduan = ['ID', '活动名称', '手机号', '抽奖时间', '领奖时间', '奖品类型', '奖品状态', '奖品活动名称', '金额', '门槛', '市公司', '区公司', '网点', '业务姓名', '业务账号', '业务金额', '业务类型']
        cols = ['id', 'activity_name', 'mobile', 'open_time', 'received_time', 'win_type', 'open_status', 'v_activity_name', 'v_amount', 'v_floor_amount', 'city_name', 'district_name', 'branch_name', 'business_name', 'business_account', 'business_amount', 'business_type']
        response = StreamingHttpResponse(self.get_customizeactivityflipcards_fromat(cols, cursor, conn, ziduan))
        response['Content-Type'] = 'application/octet-stream; charset=gbk'
        response['Content-Disposition'] = "attachment; filename*=utf-8''{}".format(escape_uri_path('定制活动抽奖明细.csv'))
        return response

    def get_customizeactivityflipcards_fromat(self, cols, cursor, conn, ziduan):
        tmp_str = ""
        # 返回文件的每一列列名
        for col in ziduan:
            tmp_str += '"%s",' % (col)
        yield tmp_str.strip(",") + "\n"
        TRADE_TYPE_ENUM = {
            1: '支付宝',
            2: '微信',
            3: '云闪付'
        }
        IS_HIT_ENUM = {
            0: '未命中',
            1: '已命中'
        }
        WIN_TYPE_ENUM = {
            1: "支付宝代金券",
            2: "微信代金券",
            3: "微信鼓励金",
            4: "谢谢参与",
            5: "积分",
            6: "支付宝鼓励金",
        }
        OPEN_STATUS_ENUM = {
            1: "初始状态",
            2: "待领取",
            3: "谢谢参与",
            4: "已领取",
            5: "失效状态",
            6: "领取失败",
        }
        BUSINESS_TYPE_ENUM = {
            1: "定期",
            2: "活期",
            3: "长期期缴"
        }
        while True:
            tmp_str = ""
            row = cursor.fetchone()
            if row is None:
                cursor.close()
                conn.close()
                break
            for col in cols:
                if col == 'win_type':
                    tmp_str += '"%s",' % (WIN_TYPE_ENUM[row[col]])
                elif col == 'open_status':
                    tmp_str += '"%s",' % (OPEN_STATUS_ENUM[row[col]])
                elif col == 'business_type':
                    try:
                        tmp_str += '"%s",' % (BUSINESS_TYPE_ENUM[row[col]])
                    except:
                        tmp_str += '"%s",' % ('')
                elif col == 'v_activity_name':
                    if row['win_type'] in [1, 2]:
                        tmp_str += '"%s",' % (row['v_activity_name'])
                    else:
                        tmp_str += '"%s",' % (row['c_activity_name'])
                elif col == 'v_amount':
                    if row['win_type'] in [1, 2]:
                        tmp_str += '"%s",' % (row['v_amount'])
                    else:
                        tmp_str += '"%s",' % (row['c_amount'])
                # elif col == 'amount':
                #     if row['payment_state'] in [1, 2, 3]:
                #         tmp_str += '"%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
                #     else:
                #         tmp_str += '"%s",' % ''
                # elif col in ['order_no', 'trade_no']:
                #     tmp_str += '"\'%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
                else:
                    tmp_str += '"%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
            yield tmp_str.strip(',') + "\n"


class MerchantSettlementRecordModelViewSet(ModelViewSet):

    pagination_class = MyPage
    filter_class = MerchantSettlementRecordFilter
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)
    search_fields = ('merchant__name', 'merchant__short_name', 'merchant__wyfMerchantID')

    def get_queryset(self):
        user = self.request.iser
        level = user.level
        level_id = self.request.query_params.get('level_id', None)
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        if level.level == 0:
            queryset = MerchantSettlementRecord.objects.all()
        elif level.level == 1:
            queryset = MerchantSettlementRecord.objects.filter(level__prov_id=level.id)
        elif level.level == 2:
            queryset = MerchantSettlementRecord.objects.filter(level__city_id=level.id)
        elif level.level == 3:
            queryset = MerchantSettlementRecord.objects.filter(level__district_id=level.id)
        else:
            queryset = MerchantSettlementRecord.objects.filter(level__branch_id=level.id)
        queryset = queryset.filter(settlement_time__gte="2023-01-01 00:00:00")
        return queryset.order_by('-settlement_time', 'id')

    def get_serializer_class(self):
        if self.action == 'list':
            return MerchantSettlementRecordListModelSerializer
        else:
            return MerchantSettlementRecordRetrieveModelSerializer

    def export_settlementrecord(self, request):
        user = self.request.iser
        settlement_time_begin = self.request.query_params.get('settlement_time_begin', None)
        settlement_time_end = self.request.query_params.get('settlement_time_end', None)
        level_id = self.request.query_params.get('level', None)
        status = self.request.query_params.get('status', None)
        channel_id = self.request.query_params.get('channel_id', None)
        search = self.request.query_params.get('search', None)
        level = user.level
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        if level.level == 0:
            condition = 'WHERE level_id IN (SELECT id FROM tb_u_level)'
        elif level.level == 1:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE prov_id={level.id})'
        elif level.level == 2:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE city_id={level.id})'
        elif level.level == 3:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE district_id={level.id})'
        else:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE branch_id={level.id})'
        if search:
            condition = condition + f' AND (merchant_id IN (SELECT id FROM tb_merchant WHERE name LIKE "%{search}%" OR short_name LIKE "%{search}%" OR wyfMerchantID LIKE "%{search}%"))'
        if status:
            condition = condition + f' AND status in ({status})'
        if channel_id:
            condition = condition + f' AND channel_id in ({channel_id})'
        if settlement_time_begin:
            condition = condition + f' AND settlement_time >= "{settlement_time_begin + " 00:00:00"}"'
        if settlement_time_end:
            condition = condition + f' AND settlement_time <= "{settlement_time_end + " 23:59:59"}"'
        condition = condition + f' AND settlement_time >= "2023-01-01 00:00:00"'
        conn = pymysql.connect(host=settings.DATABASES['default']['HOST'],
                               port=settings.DATABASES['default']['PORT'],
                               database=settings.DATABASES['default']['NAME'],
                               user=settings.DATABASES['default']['USER'],
                               password=settings.DATABASES['default']['PASSWORD'])
        cursor = conn.cursor(cursor=pymysql.cursors.SSDictCursor)
        try:
            sql = f'''
            SELECT * FROM (SELECT e.*,f.channel_name FROM (SELECT c.*,d.city_name,district_name,branch_name FROM (SELECT a.*,b.merchant_name,short_name,wyfMerchantID FROM (SELECT id,account_name,account_number,status,amount,DATE_FORMAT(settlement_time,'%Y-%m-%d %H:%i:%S')AS settlement_time,fail_reason,merchant_id,channel_id,level_id FROM tb_merchant_settlement_record {condition})AS a LEFT JOIN (SELECT id,name AS merchant_name,short_name,wyfMerchantID FROM tb_merchant)AS b ON a.merchant_id=b.id)AS c LEFT JOIN (SELECT id,city_name,district_name,branch_name FROM tb_u_level)AS d ON c.level_id=d.id)AS e LEFT JOIN (SELECT id,name AS channel_name FROM tb_channel)AS f ON e.channel_id=f.id)AS j LEFT JOIN (SELECT settlement_record_id,GROUP_CONCAT(payable_amount)AS payable_amount,GROUP_CONCAT(DATE_FORMAT(receipts_time,'%Y-%m-%d'))AS receipts_time FROM (SELECT g.bill_id,settlement_record_id,h.payable_amount,receipts_time FROM (SELECT bill_id,settlement_record_id FROM tb_merchant_bill_settlement_record)AS g LEFT JOIN (SELECT id,receipts_time,payable_amount FROM tb_merchant_bill)AS h ON g.bill_id=h.id)AS i GROUP BY settlement_record_id)AS k ON j.id=k.settlement_record_id;
            '''
            cursor.execute(sql)
        except:
            sql = f'''
            SELECT * FROM (SELECT e.*,f.channel_name FROM (SELECT c.*,d.city_name,district_name,branch_name FROM (SELECT a.*,b.merchant_name,short_name,wyfMerchantID FROM (SELECT id,account_name,account_number,status,amount,DATE_FORMAT(settlement_time,'%Y-%m-%d %H:%i:%S')AS settlement_time,fail_reason,merchant_id,channel_id,level_id FROM tb_merchant_settlement_record)AS a LEFT JOIN (SELECT id,name AS merchant_name,short_name,wyfMerchantID FROM tb_merchant)AS b ON a.merchant_id=b.id)AS c LEFT JOIN (SELECT id,city_name,district_name,branch_name FROM tb_u_level)AS d ON c.level_id=d.id)AS e LEFT JOIN (SELECT id,name AS channel_name FROM tb_channel)AS f ON e.channel_id=f.id)AS j LEFT JOIN (SELECT settlement_record_id,GROUP_CONCAT(payable_amount)AS payable_amount,GROUP_CONCAT(DATE_FORMAT(receipts_time,'%Y-%m-%d'))AS receipts_time FROM (SELECT g.bill_id,settlement_record_id,h.payable_amount,receipts_time FROM (SELECT bill_id,settlement_record_id FROM tb_merchant_bill_settlement_record)AS g LEFT JOIN (SELECT id,receipts_time,payable_amount FROM tb_merchant_bill)AS h ON g.bill_id=h.id)AS i GROUP BY settlement_record_id)AS k ON j.id=k.settlement_record_id;
            '''
            cursor.execute(sql)
        ziduan = ['结算ID', '商户全称', '商户简称', '微邮付商户号', '清分日期', '结算时间', '清分金额', '结算金额',
                  '结算状态', '结算失败原因', '归属市公司', '归属区县', '归属网点', '结算通道', '结算户名', '结算卡号']
        cols = ['id', 'merchant_name', 'short_name', 'wyfMerchantID', 'receipts_time', 'settlement_time', 'payable_amount', 'amount',
                'status', 'fail_reason', 'city_name', 'district_name', 'branch_name', 'channel_name', 'account_name', 'account_number']
        response = StreamingHttpResponse(self.get_settlementrecord_fromat(cols, cursor, conn, ziduan))
        response['Content-Type'] = 'application/octet-stream; charset=gbk'
        response['Content-Disposition'] = "attachment; filename*=utf-8''{}".format(escape_uri_path('结算单信息.csv'))
        return response

    def get_settlementrecord_fromat(self, cols, cursor, conn, ziduan):
        tmp_str = ""
        # 返回文件的每一列列名
        for col in ziduan:
            tmp_str += '"%s",' % (col)
        yield tmp_str.strip(",") + "\n"
        STATUS_ENUM = {
            1: '待结算',
            2: '结算中',
            3: '已结算',
            4: '已撤销',
            5: '结算失败'
        }
        while True:
            tmp_str = ""
            row = cursor.fetchone()
            if row is None:
                cursor.close()
                conn.close()
                break
            for col in cols:
                if col == 'status':
                    tmp_str += '"%s",' % (STATUS_ENUM[row[col]])
                else:
                    tmp_str += '"%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
            yield tmp_str.strip(',') + "\n"

    def statistical_settlement(self, request):
        time_min = self.request.query_params.get('time_min', None)
        time_max = self.request.query_params.get('time_max', None)
        user = self.request.iser
        level = user.level
        level_id = self.request.query_params.get('level', None)
        if not all([time_min, time_max]):
            return Response({'error': '缺少时间区间参数!'}, status=status.HTTP_400_BAD_REQUEST)
        try:
            time_min1 = int(time.mktime(time.strptime(str(time_min) + ' 00:00:00', "%Y-%m-%d %H:%M:%S")))
            time_max1 = int(time.mktime(time.strptime(str(time_max) + ' 00:00:00', "%Y-%m-%d %H:%M:%S")))
        except:
            return Response({'error': '时间区间参数有误!'}, status=status.HTTP_400_BAD_REQUEST)
        if time_max1 - time_min1 > 2678400:
            return Response({'error': '时区不得大于31天!'}, status=status.HTTP_400_BAD_REQUEST)
        time_min1 = time_min + ' 00:00:00'
        time_max1 = time_max + ' 23:59:59'
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        if level.level == 0:
            condition = ''
        elif level.level == 1:
            condition = f'AND level_id IN (SELECT id FROM tb_u_level WHERE prov_id={level.id})'
        elif level.level == 2:
            condition = f'AND level_id IN (SELECT id FROM tb_u_level WHERE city_id={level.id})'
        elif level.level == 3:
            condition = f'AND level_id IN (SELECT id FROM tb_u_level WHERE district_id={level.id})'
        else:
            condition = f'AND level_id IN (SELECT id FROM tb_u_level WHERE branch_id={level.id})'
        sxf_amount_data = {}
        ryx_amount_data = {}
        total_amount_data = {}
        sxf_data = []
        ryx_data = []
        total_data = []
        data = {}
        max_amount = 0
        sxf_amount_sum = 0
        ryx_amount_sum = 0
        total_amount_sum = 0
        conn = pymysql.connect(host=settings.DATABASES['default']['HOST'],
                               port=settings.DATABASES['default']['PORT'],
                               database=settings.DATABASES['default']['NAME'],
                               user=settings.DATABASES['default']['USER'],
                               password=settings.DATABASES['default']['PASSWORD'])
        cursor = conn.cursor(cursor=pymysql.cursors.SSDictCursor)
        xAxis = []
        time_min = datetime.datetime.strptime(time_min, "%Y-%m-%d").date()
        time_max = datetime.datetime.strptime(time_max, "%Y-%m-%d").date()
        create_begin_time = time_min
        days_num = (time_max-time_min).days + 1
        begin_day = time_min
        sql = f'''SELECT DATE_FORMAT(settlement_time,'%Y-%m-%d')AS time,SUM(CASE channel_id WHEN 3 THEN amount ELSE 0 END)AS sxf_amount,SUM(CASE channel_id WHEN 2 THEN amount ELSE 0 END)AS ryx_amount,SUM(amount)AS total_amount FROM tb_merchant_settlement_record WHERE settlement_time>="{time_min1}" AND settlement_time<="{time_max1}" AND status=3 {condition} GROUP BY time;'''
        cursor.execute(sql)
        result = cursor.fetchall()
        while True:
            if begin_day > time_max:
                break
            xAxis.append(datetime.datetime.strftime(begin_day, '%m/%d'))
            begin_day += datetime.timedelta(days=1)
        if result:
            while True:
                if datetime.datetime.strptime(result[0]['time'], "%Y-%m-%d").date() <= create_begin_time:
                    break
                sxf_data.append(0)
                ryx_data.append(0)
                total_data.append(0)
                create_begin_time += datetime.timedelta(days=1)
            for x in result:
                while True:
                    if datetime.datetime.strptime(x['time'], "%Y-%m-%d").date() < create_begin_time:
                        break
                    if datetime.datetime.strptime(x['time'], "%Y-%m-%d").date() == create_begin_time:
                        sxf_data.append(x['sxf_amount'])
                        ryx_data.append(x['ryx_amount'])
                        total_data.append(x['total_amount'])
                        sxf_amount_sum += x['sxf_amount']
                        ryx_amount_sum += x['ryx_amount']
                        total_amount_sum += x['total_amount']
                        if max_amount < x['total_amount']:
                            max_amount = x['total_amount']
                    else:
                        sxf_data.append(0)
                        ryx_data.append(0)
                        total_data.append(0)
                    create_begin_time += datetime.timedelta(days=1)
            while True:
                if len(sxf_data) >= days_num:
                    break
                sxf_data.append(0)
                ryx_data.append(0)
                total_data.append(0)
        else:
            for i in range(days_num):
                sxf_data.append(0)
                ryx_data.append(0)
                total_data.append(0)
        sxf_amount_data['name'] = '随行付结算金额'
        sxf_amount_data['data'] = sxf_data
        ryx_amount_data['name'] = '瑞银信结算金额'
        ryx_amount_data['data'] = ryx_data
        total_amount_data['name'] = '总结算金额'
        total_amount_data['data'] = total_data
        cursor.close()
        conn.close()
        if max_amount:
            str_max_amount = str(max_amount)
            if '.' in str_max_amount:
                len_max_amount = len(str_max_amount[:str_max_amount.find('.')])
            else:
                len_max_amount = len(str_max_amount)
            to_max_amount = '1'
            while True:
                if len(to_max_amount) >= len_max_amount -1:
                    to_max_amount = int(to_max_amount)
                    break
                to_max_amount += '0'
            max_amount = math.ceil(max_amount/to_max_amount)*to_max_amount
        data['sxf_amount_data'] = sxf_amount_data
        data['ryx_amount_data'] = ryx_amount_data
        data['total_amount_data'] = total_amount_data
        data['max_amount'] = max_amount
        data['xAxis'] = xAxis
        data['ryx_amount_sum'] = ryx_amount_sum
        data['sxf_amount_sum'] = sxf_amount_sum
        data['total_amount_sum'] = total_amount_sum
        return Response(data, status=status.HTTP_200_OK)

    def export_statistical_settlement(self, request):
        time_min = self.request.query_params.get('time_min', None)
        time_max = self.request.query_params.get('time_max', None)
        user = self.request.iser
        level = user.level
        level_id = self.request.query_params.get('level', None)
        if not all([time_min, time_max]):
            return Response({'error': '缺少时间区间参数!'}, status=status.HTTP_400_BAD_REQUEST)
        try:
            time_min1 = int(time.mktime(time.strptime(str(time_min) + ' 00:00:00', "%Y-%m-%d %H:%M:%S")))
            time_max1 = int(time.mktime(time.strptime(str(time_max) + ' 00:00:00', "%Y-%m-%d %H:%M:%S")))
        except:
            return Response({'error': '时间区间参数有误!'}, status=status.HTTP_400_BAD_REQUEST)
        time_min1 = time_min + ' 00:00:00'
        time_max1 = time_max + ' 23:59:59'
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        if level.level == 0:
            condition = ''
        elif level.level == 1:
            condition = f'AND level_id IN (SELECT id FROM tb_u_level WHERE prov_id={level.id})'
        elif level.level == 2:
            condition = f'AND level_id IN (SELECT id FROM tb_u_level WHERE city_id={level.id})'
        elif level.level == 3:
            condition = f'AND level_id IN (SELECT id FROM tb_u_level WHERE district_id={level.id})'
        else:
            condition = f'AND level_id IN (SELECT id FROM tb_u_level WHERE branch_id={level.id})'
        conn = pymysql.connect(host=settings.DATABASES['default']['HOST'],
                               port=settings.DATABASES['default']['PORT'],
                               database=settings.DATABASES['default']['NAME'],
                               user=settings.DATABASES['default']['USER'],
                               password=settings.DATABASES['default']['PASSWORD'])
        cursor = conn.cursor(cursor=pymysql.cursors.SSDictCursor)
        sql = f'''
        SELECT DATE_FORMAT(settlement_time,'%Y-%m-%d')AS time,SUM(CASE channel_id WHEN 3 THEN amount ELSE 0 END)AS sxf_amount,SUM(CASE channel_id WHEN 2 THEN amount ELSE 0 END)AS ryx_amount,SUM(amount)AS total_amount FROM tb_merchant_settlement_record WHERE settlement_time>="{time_min1}" AND settlement_time<="{time_max1}" AND status=3 {condition} GROUP BY time;
        '''
        cursor.execute(sql)
        ziduan = ['日期', '机构名称', '总结算金额', '瑞银信结算金额', '随行付结算金额']
        cols = ['time', 'name', 'total_amount', 'ryx_amount', 'sxf_amount']
        response = StreamingHttpResponse(self.get_statistical_settlement_fromat(cols, cursor, conn, ziduan, level.name))
        response['Content-Type'] = 'application/octet-stream; charset=gbk'
        response['Content-Disposition'] = "attachment; filename*=utf-8''{}".format(escape_uri_path('结算统计.csv'))
        return response

    def get_statistical_settlement_fromat(self, cols, cursor, conn, ziduan, level_name):
        tmp_str = ""
        # 返回文件的每一列列名
        for col in ziduan:
            tmp_str += '"%s",' % (col)
        yield tmp_str.strip(",") + "\n"
        while True:
            tmp_str = ""
            row = cursor.fetchone()
            if row is None:
                cursor.close()
                conn.close()
                break
            for col in cols:
                if col == 'name':
                    tmp_str += '"%s",' % (level_name)
                else:
                    tmp_str += '"%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else 0)
            yield tmp_str.strip(',') + "\n"


class MerchantEightEightDrawModelViewSet(ModelViewSet):

    pagination_class = MyPage
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)
    search_fields = ('business_no', 'merchantuser__mobile')
    filter_class = MerchantEightEightDrawFilter

    def get_queryset(self):
        user = self.request.iser
        level = user.level
        level_id = self.request.query_params.get('level_id', None)
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        if level.level == 0:
            queryset = MerchantEightEightDraw.objects.all()
        elif level.level == 1:
            queryset = MerchantEightEightDraw.objects.filter(level__prov_id=level.id)
        elif level.level == 2:
            queryset = MerchantEightEightDraw.objects.filter(level__city_id=level.id)
        elif level.level == 3:
            queryset = MerchantEightEightDraw.objects.filter(level__district_id=level.id)
        else:
            queryset = MerchantEightEightDraw.objects.filter(level__branch_id=level.id)
        return queryset.filter(id__gt=16).exclude(win_type=6).order_by('-id')

    def get_serializer_class(self):
        if self.action == 'list':
            return MerchantEightEightDrawListModelSerializer
        else:
            return MerchantEightEightDrawRetrieveModelSerializer

    def export_merchanteightdraw(self, request):
        user = self.request.iser
        level_id = self.request.query_params.get('level_id', None)
        create_time_begin = self.request.query_params.get('create_time_begin', None)
        create_time_end = self.request.query_params.get('create_time_end', None)
        amount_min = self.request.query_params.get('amount_min', None)
        amount_max = self.request.query_params.get('amount_max', None)
        state = self.request.query_params.get('state', None)
        search = self.request.query_params.get('search', None)
        activity_id = self.request.query_params.get('activity_id', None)
        level = user.level
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        if level.level == 0:
            condition = 'WHERE win_type!=6 AND id>16'
        elif level.level == 1:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE prov_id={level.id}) AND win_type!=6 AND id>16'
        elif level.level == 2:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE city_id={level.id}) AND win_type!=6 AND id>16'
        elif level.level == 3:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE district_id={level.id}) AND win_type!=6 AND id>16'
        else:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE branch_id={level.id}) AND win_type!=6 AND id>16'
        if search:
            condition = condition + f' AND (merchantuser_id IN (SELECT id FROM tb_m_merchant_user WHERE mobile LIKE "%{search}%") OR business_no LIKE "%{search}%")'
        if state:
            condition = condition + f' AND state in ({state})'
        if create_time_begin:
            condition = condition + f' AND create_time >= "{create_time_begin + " 00:00:00"}"'
        if create_time_end:
            condition = condition + f' AND create_time <= "{create_time_end + " 23:59:59"}"'
        if amount_min:
            condition = condition + f' AND amount >= {amount_min}'
        if amount_max:
            condition = condition + f' AND amount <= {amount_max}'
        if activity_id:
            condition = condition + f' AND activity_id = {activity_id}'

        conn = pymysql.connect(host=settings.DATABASES['default']['HOST'],
                               port=settings.DATABASES['default']['PORT'],
                               database=settings.DATABASES['default']['NAME'],
                               user=settings.DATABASES['default']['USER'],
                               password=settings.DATABASES['default']['PASSWORD'])
        cursor = conn.cursor(cursor=pymysql.cursors.SSDictCursor)
        try:
            sql = f'''
            SELECT g.*,h.activity_name FROM (SELECT * FROM (SELECT c.*,d.city_name,district_name,branch_name FROM (SELECT a.*,b.mobile FROM (SELECT id,business_no,amount,payment_no,state,merchantuser_id,DATE_FORMAT(create_time,'%Y-%m-%d %H:%i:%S')AS create_time,DATE_FORMAT(received_time,'%Y-%m-%d %H:%i:%S')AS received_time,login_id,realname,return_msg,level_id,activity_id FROM tb_merchant_eigth_eight_draw {condition})AS a LEFT JOIN (SELECT id,mobile FROM tb_m_merchant_user)AS b ON a.merchantuser_id=b.id)AS c LEFT JOIN (SELECT id,city_name,district_name,branch_name FROM tb_u_level)AS d ON c.level_id=d.id)AS e LEFT JOIN (SELECT wyfMerchantID,short_name FROM tb_merchant)AS f ON e.business_no=f.wyfMerchantID)AS g LEFT JOIN (SELECT activity_id,activity_name FROM tb_merchant_eight_eight_activity)AS h ON g.activity_id=h.activity_id;
            '''
            cursor.execute(sql)
        except:
            sql = f'''
            SELECT g.*,h.activity_name FROM (SELECT * FROM (SELECT c.*,d.city_name,district_name,branch_name FROM (SELECT a.*,b.mobile FROM (SELECT id,business_no,amount,payment_no,state,merchantuser_id,DATE_FORMAT(create_time,'%Y-%m-%d %H:%i:%S')AS create_time,DATE_FORMAT(received_time,'%Y-%m-%d %H:%i:%S')AS received_time,login_id,realname,return_msg,level_id,activity_id FROM tb_merchant_eigth_eight_draw)AS a LEFT JOIN (SELECT id,mobile FROM tb_m_merchant_user)AS b ON a.merchantuser_id=b.id)AS c LEFT JOIN (SELECT id,city_name,district_name,branch_name FROM tb_u_level)AS d ON c.level_id=d.id)AS e LEFT JOIN (SELECT wyfMerchantID,short_name FROM tb_merchant)AS f ON e.business_no=f.wyfMerchantID)AS g LEFT JOIN (SELECT activity_id,activity_name FROM tb_merchant_eight_eight_activity)AS h ON g.activity_id=h.activity_id;
            '''
            cursor.execute(sql)
        ziduan = ['ID', '活动名称', '商户号', '商户简称', '付款单号', '状态', '中奖金额', '抽奖时间', '领奖时间', '领奖账号', '实名姓名', '领奖人手机号', '市公司', '区公司', '网点', '领取失败原因']
        cols = ['id', 'activity_name', 'business_no', 'short_name', 'payment_no', 'state', 'amount', 'create_time', 'received_time', 'login_id', 'realname', 'mobile', 'city_name', 'district_name', 'branch_name', 'return_msg']
        response = StreamingHttpResponse(self.get_merchanteightdraw_fromat(cols, cursor, conn, ziduan))
        response['Content-Type'] = 'application/octet-stream; charset=gbk'
        response['Content-Disposition'] = "attachment; filename*=utf-8''{}".format(escape_uri_path('88节达标商户中奖明细.csv'))
        return response

    def get_merchanteightdraw_fromat(self, cols, cursor, conn, ziduan):
        tmp_str = ""
        # 返回文件的每一列列名
        for col in ziduan:
            tmp_str += '"%s",' % (col)
        yield tmp_str.strip(",") + "\n"
        STATE_ENUM = {
            1: '待领取',
            2: '已领取',
            3: '领取失败',
            5: '领取中'
        }
        while True:
            tmp_str = ""
            row = cursor.fetchone()
            if row is None:
                cursor.close()
                conn.close()
                break
            for col in cols:
                if col == 'state':
                    tmp_str += '"%s",' % (STATE_ENUM[row[col]])
                elif col == 'return_msg':
                    if row['state'] == 3:
                        tmp_str += '"%s",' % (row[col])
                elif col == 'login_id':
                    login_id = row[col]
                    if login_id:
                        try:
                            if '@' in login_id:
                                login_id = f'{login_id[:3]}****{login_id[login_id.find("@"):]}'
                            else:
                                login_id = f'{login_id[:3]}****{login_id[-4:]}'
                        except:
                            login_id = ''
                    else:
                        login_id = ''
                    tmp_str += '"%s",' % (login_id)
                elif col == 'realname':
                    realname = row[col]
                    if realname:
                        try:
                            realname = f'{realname.replace(realname[-2], "*", 1)}'
                        except:
                            realname = ''
                    else:
                        realname = ''
                    tmp_str += '"%s",' % (realname)
                elif col == 'mobile':
                    mobile = row[col]
                    if mobile:
                        try:
                            mobile = f'{mobile[:3]}****{mobile[-4:]}'
                        except:
                            mobile = ''
                    else:
                        mobile = ''
                    tmp_str += '"%s",' % (mobile)
                elif col in ['payment_no']:
                    tmp_str += '"\'%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
                else:
                    tmp_str += '"%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
            yield tmp_str.strip(',') + "\n"


class MerchantBusinessQRCodeModelViewSet(ModelViewSet):

    pagination_class = MyPage
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)
    search_fields = ('merchant__wyfMerchantID', 'sn')
    filter_class = MerchantBusinessQRCodeFilter

    def get_queryset(self):
        user = self.request.iser
        level = user.level
        level_id = self.request.query_params.get('level_id', None)
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        if level.level == 0:
            queryset = MerchantBusinessQRCode.objects.all()
        elif level.level == 1:
            queryset = MerchantBusinessQRCode.objects.filter(level__prov_id=level.id)
        elif level.level == 2:
            queryset = MerchantBusinessQRCode.objects.filter(level__city_id=level.id)
        elif level.level == 3:
            queryset = MerchantBusinessQRCode.objects.filter(level__district_id=level.id)
        else:
            queryset = MerchantBusinessQRCode.objects.filter(level__branch_id=level.id)
        return queryset

    def get_serializer_class(self):
        if self.action == 'list':
            return MerchantBusinessQRCodeListModelSerializer
        else:
            return MerchantBusinessQRCodeRetrieveModelSerializer

    def export_merchantbusinessqrcode(self, request):
        user = self.request.iser
        level = user.level
        level_id = self.request.query_params.get('level_id', None)
        bind_time_begin = self.request.query_params.get('bind_time_begin', None)
        bind_time_end = self.request.query_params.get('bind_time_end', None)
        is_bind = self.request.query_params.get('is_bind', None)
        search = self.request.query_params.get('search', None)
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        if level.level == 0:
            condition = 'WHERE id!=0'
        elif level.level == 1:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE prov_id={level.id})'
        elif level.level == 2:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE city_id={level.id})'
        elif level.level == 3:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE district_id={level.id})'
        else:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE branch_id={level.id})'
        if search:
            condition = condition + f' AND (sn LIKE "%{search}%" OR merchant_id IN (SELECT id FROM tb_merchant WHERE wyfMerchantID LIKE "%{search}%"))'
        if bind_time_begin:
            condition = condition + f' AND bind_time >= "{bind_time_begin + " 00:00:00"}"'
        if bind_time_end:
            condition = condition + f' AND bind_time <= "{bind_time_end + " 23:59:59"}"'
        if is_bind:
            condition = condition + f' AND is_bind IN ({is_bind})'
        conn = pymysql.connect(host=settings.DATABASES['default']['HOST'],
                               port=settings.DATABASES['default']['PORT'],
                               database=settings.DATABASES['default']['NAME'],
                               user=settings.DATABASES['default']['USER'],
                               password=settings.DATABASES['default']['PASSWORD'])
        cursor = conn.cursor(cursor=pymysql.cursors.SSDictCursor)
        try:
            sql = f'''
            SELECT k.*,l.mobile FROM (SELECT i.*,j.state,received_time,amount FROM (SELECT g.*,h.visit_count FROM (SELECT e.*,f.nickname FROM (SELECT c.*,d.city_name,district_name,branch_name FROM (SELECT a.*,b.name,short_name,wyfMerchantID FROM (SELECT id,sn,merchant_id,DATE_FORMAT(bind_time,'%Y-%m-%d %H:%i:%S') AS bind_time,is_bind,customeruservice_id,is_c_bind,DATE_FORMAT(c_bind_time,'%Y-%m-%d %H:%i:%S') AS c_bind_time,level_id,user_id,inviter_count,inviter_total_count,DATE_FORMAT(award_time,'%Y-%m-%d %H:%i:%S') AS award_time,is_achieve,cashactivitydata_id FROM tb_merchant_business_qrcode {condition})AS a LEFT JOIN (SELECT id,name,short_name,wyfMerchantID FROM tb_merchant)AS b ON a.merchant_id=b.id)AS c LEFT JOIN (SELECT id,city_name,district_name,branch_name FROM tb_u_level)AS d ON c.level_id=d.id)AS e LEFT JOIN (SELECT id,nickname FROM tb_u_user)AS f ON e.user_id=f.id)AS g LEFT JOIN (SELECT qrcode_id,COUNT(qrcode_id) AS visit_count FROM tb_merchant_business_qrcode_visit GROUP BY qrcode_id)AS h ON g.id=h.qrcode_id)AS i LEFT JOIN (SELECT id,state,received_time,amount FROM tb_cash_activity_data)AS j ON i.cashactivitydata_id=j.id)AS k LEFT JOIN (SELECT id,mobile FROM tb_u_customer_user_vice)AS l ON k.customeruservice_id=l.id;
            '''
            cursor.execute(sql)
        except Exception as e:
            sql = f'''
            SELECT k.*,l.mobile FROM (SELECT i.*,j.state,received_time,amount FROM (SELECT g.*,h.visit_count FROM (SELECT e.*,f.nickname FROM (SELECT c.*,d.city_name,district_name,branch_name FROM (SELECT a.*,b.name,short_name,wyfMerchantID FROM (SELECT id,sn,merchant_id,DATE_FORMAT(bind_time,'%Y-%m-%d %H:%i:%S') AS bind_time,is_bind,customeruservice_id,is_c_bind,DATE_FORMAT(c_bind_time,'%Y-%m-%d %H:%i:%S') AS c_bind_time,level_id,user_id,inviter_count,inviter_total_count,DATE_FORMAT(award_time,'%Y-%m-%d %H:%i:%S') AS award_time,is_achieve,cashactivitydata_id FROM tb_merchant_business_qrcode)AS a LEFT JOIN (SELECT id,name,short_name,wyfMerchantID FROM tb_merchant)AS b ON a.merchant_id=b.id)AS c LEFT JOIN (SELECT id,city_name,district_name,branch_name FROM tb_u_level)AS d ON c.level_id=d.id)AS e LEFT JOIN (SELECT id,nickname FROM tb_u_user)AS f ON e.user_id=f.id)AS g LEFT JOIN (SELECT qrcode_id,COUNT(qrcode_id) AS visit_count FROM tb_merchant_business_qrcode_visit GROUP BY qrcode_id)AS h ON g.id=h.qrcode_id)AS i LEFT JOIN (SELECT id,state,received_time,amount FROM tb_cash_activity_data)AS j ON i.cashactivitydata_id=j.id)AS k LEFT JOIN (SELECT id,mobile FROM tb_u_customer_user_vice)AS l ON k.customeruservice_id=l.id;
            '''
            cursor.execute(sql)
        ziduan = ['id', '商圈编码', '码牌绑定状态', '绑定时间', '微邮付商户号', '商户全称', '商户简称', '市公司', '区县', '网点', '客户经理姓名', '店主绑定状态', '店主绑定时间', '客户经理领取奖励状态', '领奖时间', '领取奖励金额']
        cols = ['id', 'sn', 'is_bind', 'bind_time', 'wyfMerchantID', 'name', 'short_name', 'city_name', 'district_name', 'branch_name', 'nickname', 'is_c_bind', 'c_bind_time', 'state', 'received_time', 'amount']
        response = StreamingHttpResponse(self.get_merchantbusinessqrcode_fromat(cols, cursor, conn, ziduan))
        response['Content-Type'] = 'application/octet-stream; charset=gbk'
        response['Content-Disposition'] = "attachment; filename*=utf-8''{}".format(escape_uri_path('商圈码绑定状态.csv'))
        return response

    def get_merchantbusinessqrcode_fromat(self, cols, cursor, conn, ziduan):
        tmp_str = ""
        # 返回文件的每一列列名
        for col in ziduan:
            tmp_str += '"%s",' % (col)
        yield tmp_str.strip(",") + "\n"
        IS_BIND_ENUM = {
            0: '未绑定',
            1: '已绑定'
        }
        STATE_ENUM = {
            1: '待领取',
            2: '已领取',
            3: '领取失败',
            4: '已撤销',
            5: '领取中'
        }
        while True:
            tmp_str = ""
            row = cursor.fetchone()
            if row is None:
                cursor.close()
                conn.close()
                break
            for col in cols:
                if col in ['is_bind', 'is_c_bind']:
                    tmp_str += '"%s",' % (IS_BIND_ENUM[row[col]])
                elif col == 'state':
                    try:
                        tmp_str += '"%s",' % (STATE_ENUM[row[col]])
                    except:
                        tmp_str += '"%s",' % ('待领取')
                else:
                    tmp_str += '"%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
            yield tmp_str.strip(',') + "\n"


class MerchantEightEightActivityModelViewSet(ModelViewSet):

    serializer_class = MerchantEightEightActivityModelSerializer
    pagination_class = MyPage
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)
    search_fields = ('activity_name', )
    filter_class = MerchantEightEightActivityFilter

    def get_queryset(self):
        today = datetime.datetime.now()
        user = self.request.iser
        level = user.level
        level_id = self.request.query_params.get('level_id', None)
        if level_id:
            try:
                level_list = get_level_list(level)
                level_id = int(level_id)
                if level_id in level_list:
                    level = Level.objects.filter(id=level_id).first()
            except:
                pass
        queryset = MerchantEightEightActivity.objects.filter(merchanteighteightactivityrelevance__level_id=level.id)
        return queryset.filter(activity_end_time__gte=today, activity_start_time__lte=today).order_by('-activity_end_time')


class MerchantEightEightWhiteTableModelViewSet(ModelViewSet):

    serializer_class = MerchantEightEightWhiteTableModelSerializer
    pagination_class = MyPage
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)
    search_fields = ('business_no', )

    def get_queryset(self):
        user = self.request.iser
        level = user.level
        activity_id = self.request.query_params.get('activity_id', None)
        if activity_id:
            activity = MerchantEightEightActivity.objects.filter(id=activity_id).first()
            if activity.activity_type == 3:
                # queryset = MerchantEightEightActivityOrder.objects.all()
                if level.level == 0:
                    queryset = MerchantEightEightActivityOrder.objects.all()
                elif level.level == 1:
                    queryset = MerchantEightEightActivityOrder.objects.filter(level__prov_id=level.id)
                elif level.level == 2:
                    queryset = MerchantEightEightActivityOrder.objects.filter(level__city_id=level.id)
                elif level.level == 3:
                    queryset = MerchantEightEightActivityOrder.objects.filter(level__district_id=level.id)
                else:
                    queryset = MerchantEightEightActivityOrder.objects.filter(level__branch_id=level.id)
            else:
                if level.level == 0:
                    queryset = MerchantEightEightWhiteTable.objects.all()
                elif level.level == 1:
                    queryset = MerchantEightEightWhiteTable.objects.filter(level__prov_id=level.id)
                elif level.level == 2:
                    queryset = MerchantEightEightWhiteTable.objects.filter(level__city_id=level.id)
                elif level.level == 3:
                    queryset = MerchantEightEightWhiteTable.objects.filter(level__district_id=level.id)
                else:
                    queryset = MerchantEightEightWhiteTable.objects.filter(level__branch_id=level.id)
        else:
            if level.level == 0:
                queryset = MerchantEightEightWhiteTable.objects.all()
            elif level.level == 1:
                queryset = MerchantEightEightWhiteTable.objects.filter(level__prov_id=level.id)
            elif level.level == 2:
                queryset = MerchantEightEightWhiteTable.objects.filter(level__city_id=level.id)
            elif level.level == 3:
                queryset = MerchantEightEightWhiteTable.objects.filter(level__district_id=level.id)
            else:
                queryset = MerchantEightEightWhiteTable.objects.filter(level__branch_id=level.id)
        queryset = queryset.filter(activity_id=activity_id)
        return queryset

    def get_serializer_class(self):
        activity_id = self.request.query_params.get('activity_id', None)
        if activity_id:
            activity = MerchantEightEightActivity.objects.filter(id=activity_id).first()
            if activity.activity_type == 3:
                return MerchantEightEightActivityOrderModelSerializer
            else:
                return MerchantEightEightWhiteTableModelSerializer
        else:
            return MerchantEightEightWhiteTableModelSerializer

    def export_merchantreachwhitetable(self, request):
        user = self.request.iser
        level = user.level
        activity_id = self.request.query_params.get('activity_id', None)
        conn = pymysql.connect(host=settings.DATABASES['default']['HOST'],
                               port=settings.DATABASES['default']['PORT'],
                               database=settings.DATABASES['default']['NAME'],
                               user=settings.DATABASES['default']['USER'],
                               password=settings.DATABASES['default']['PASSWORD'])
        cursor = conn.cursor(cursor=pymysql.cursors.SSDictCursor)
        if level.level == 0:
            condition = f'WHERE activity_id={activity_id}'
        elif level.level == 1:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE prov_id={level.id}) AND activity_id={activity_id}'
        elif level.level == 2:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE city_id={level.id}) AND activity_id={activity_id}'
        elif level.level == 3:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE district_id={level.id}) AND activity_id={activity_id}'
        else:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE branch_id={level.id}) AND activity_id={activity_id}'
        if activity_id:
            activity = MerchantEightEightActivity.objects.filter(id=activity_id).first()
            if activity.activity_type == 3:
                sql = f'SELECT * FROM (SELECT * FROM (SELECT business_no,activity_id,is_standard,trade_amount,DATE_FORMAT(trade_time,"%Y-%m-%d")AS trade_time FROM tb_merchant_eight_eight_activity_order {condition})AS a LEFT JOIN (SELECT name,wyfMerchantID,subject_type,level_id FROM tb_merchant)AS b ON a.business_no=b.wyfMerchantID)AS c LEFT JOIN (SELECT id,city_name,district_name,branch_name FROM tb_u_level)AS d ON c.level_id=d.id;'
                ziduan = ['商户号', '商户名称', '商户类型', '所属市公司', '所属区县', '所属网点', '交易日期', '交易金额', '是否达标']
                cols = ['business_no', 'name', 'subject_type', 'city_name', 'district_name', 'branch_name', 'trade_time', 'trade_amount', 'is_standard']
            else:
                sql = f'SELECT * FROM (SELECT * FROM (SELECT business_no,activity_id FROM tb_merchant_eigth_eight_white_table {condition})AS a LEFT JOIN (SELECT name,wyfMerchantID,subject_type,level_id FROM tb_merchant)AS b ON a.business_no=b.wyfMerchantID)AS c LEFT JOIN (SELECT id,city_name,district_name,branch_name FROM tb_u_level)AS d ON c.level_id=d.id;'
                ziduan = ['商户号', '商户名称', '商户类型', '所属市公司', '所属区县', '所属网点']
                cols = ['business_no', 'name', 'subject_type', 'city_name', 'district_name', 'branch_name']
        else:
            sql = 'SELECT * FROM (SELECT * FROM (SELECT business_no,activity_id FROM tb_merchant_eigth_eight_white_table WHERE activity_id=0)AS a LEFT JOIN (SELECT name,wyfMerchantID,subject_type,level_id FROM tb_merchant)AS b ON a.business_no=b.wyfMerchantID)AS c LEFT JOIN (SELECT id,city_name,district_name,branch_name FROM tb_u_level)AS d ON c.level_id=d.id;'
            ziduan = ['商户号', '商户名称', '商户类型', '所属市公司', '所属区县', '所属网点']
            cols = ['business_no', 'name', 'subject_type', 'city_name', 'district_name', 'branch_name']
        try:
            cursor.execute(sql)
        except:
            sql = 'SELECT * FROM (SELECT * FROM (SELECT business_no,activity_id FROM tb_merchant_eigth_eight_white_table WHERE activity_id=0)AS a LEFT JOIN (SELECT name,wyfMerchantID,subject_type,level_id FROM tb_merchant)AS b ON a.business_no=b.wyfMerchantID)AS c LEFT JOIN (SELECT id,city_name,district_name,branch_name FROM tb_u_level)AS d ON c.level_id=d.id;'
            cursor.execute(sql)
        response = StreamingHttpResponse(self.get_merchantreachwhitetable_fromat(cols, cursor, conn, ziduan))
        response['Content-Type'] = 'application/octet-stream; charset=gbk'
        response['Content-Disposition'] = "attachment; filename*=utf-8''{}".format(escape_uri_path('交易达标商户明细.csv'))
        return response

    def get_merchantreachwhitetable_fromat(self, cols, cursor, conn, ziduan):
        tmp_str = ""
        # 返回文件的每一列列名
        for col in ziduan:
            tmp_str += '"%s",' % (col)
        yield tmp_str.strip(",") + "\n"
        SUBJECT_TYPE_ENUM = {
            1: '小微',
            2: '个体',
            3: '企业',
            4: '其他',
            5: '事业单位'
        }
        IS_STANDARDS_ENUM = {
            0: '否',
            1: '是'
        }
        while True:
            tmp_str = ""
            row = cursor.fetchone()
            if row is None:
                cursor.close()
                conn.close()
                break
            for col in cols:
                if col == 'subject_type':
                    tmp_str += '"%s",' % (SUBJECT_TYPE_ENUM[row[col]])
                elif col == 'is_standard':
                    tmp_str += '"%s",' % (IS_STANDARDS_ENUM[row[col]])
                elif col == 'trade_amount':
                    tmp_str += '"%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '0')
                else:
                    tmp_str += '"%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
            yield tmp_str.strip(',') + "\n"


class MerchantEightEightActivityOrderModelViewSet(ModelViewSet):

    pagination_class = MyPage
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)
    search_fields = ('business_no', )

    def get_queryset(self):
        user = self.request.iser
        level = user.level
        activity_id = self.request.query_params.get('activity_id', None)
        if level.level == 0:
            queryset = MerchantEightEightWhiteTable.objects.all()
        elif level.level == 1:
            queryset = MerchantEightEightWhiteTable.objects.filter(level__prov_id=level.id)
        elif level.level == 2:
            queryset = MerchantEightEightWhiteTable.objects.filter(level__city_id=level.id)
        elif level.level == 3:
            queryset = MerchantEightEightWhiteTable.objects.filter(level__district_id=level.id)
        else:
            queryset = MerchantEightEightWhiteTable.objects.filter(level__branch_id=level.id)
        if activity_id:
            queryset = queryset.filter(activity_id=activity_id)
        return queryset

    def get_serializer_class(self):
        return MerchantEightEightWhiteTableModelSerializer

    def export_merchantreachordertable(self, request):
        user = self.request.iser
        level = user.level
        activity_id = self.request.query_params.get('activity_id', None)
        conn = pymysql.connect(host=settings.DATABASES['default']['HOST'],
                               port=settings.DATABASES['default']['PORT'],
                               database=settings.DATABASES['default']['NAME'],
                               user=settings.DATABASES['default']['USER'],
                               password=settings.DATABASES['default']['PASSWORD'])
        cursor = conn.cursor(cursor=pymysql.cursors.SSDictCursor)
        if level.level == 0:
            condition = f'WHERE activity_id={activity_id}'
        elif level.level == 1:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE prov_id={level.id}) AND activity_id={activity_id}'
        elif level.level == 2:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE city_id={level.id}) AND activity_id={activity_id}'
        elif level.level == 3:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE district_id={level.id}) AND activity_id={activity_id}'
        else:
            condition = f'WHERE level_id IN (SELECT id FROM tb_u_level WHERE branch_id={level.id}) AND activity_id={activity_id}'
        sql = f'SELECT * FROM (SELECT * FROM (SELECT business_no,activity_id FROM tb_merchant_eigth_eight_white_table {condition})AS a LEFT JOIN (SELECT name,wyfMerchantID,subject_type,level_id FROM tb_merchant)AS b ON a.business_no=b.wyfMerchantID)AS c LEFT JOIN (SELECT id,city_name,district_name,branch_name FROM tb_u_level)AS d ON c.level_id=d.id;'
        ziduan = ['商户号', '商户名称', '商户类型', '所属市公司', '所属区县', '所属网点']
        cols = ['business_no', 'name', 'subject_type', 'city_name', 'district_name', 'branch_name']
        try:
            cursor.execute(sql)
        except:
            sql = 'SELECT * FROM (SELECT * FROM (SELECT business_no,activity_id FROM tb_merchant_eigth_eight_white_table WHERE activity_id=0)AS a LEFT JOIN (SELECT name,wyfMerchantID,subject_type,level_id FROM tb_merchant)AS b ON a.business_no=b.wyfMerchantID)AS c LEFT JOIN (SELECT id,city_name,district_name,branch_name FROM tb_u_level)AS d ON c.level_id=d.id;'
            cursor.execute(sql)
        # ziduan = ['商户号', '商户名称', '商户类型', '所属市公司', '所属区县', '所属网点']
        # cols = ['business_no', 'name', 'subject_type', 'city_name', 'district_name', 'branch_name']
        response = StreamingHttpResponse(self.get_merchantreachordertable_fromat(cols, cursor, conn, ziduan))
        response['Content-Type'] = 'application/octet-stream; charset=gbk'
        response['Content-Disposition'] = "attachment; filename*=utf-8''{}".format(escape_uri_path('交易达标商户明细.csv'))
        return response

    def get_merchantreachordertable_fromat(self, cols, cursor, conn, ziduan):
        tmp_str = ""
        # 返回文件的每一列列名
        for col in ziduan:
            tmp_str += '"%s",' % (col)
        yield tmp_str.strip(",") + "\n"
        SUBJECT_TYPE_ENUM = {
            1: '小微',
            2: '个体',
            3: '企业',
            4: '其他',
            5: '事业单位'
        }
        IS_STANDARDS_ENUM = {
            0: '否',
            1: '是',
            2: '是'
        }
        while True:
            tmp_str = ""
            row = cursor.fetchone()
            if row is None:
                cursor.close()
                conn.close()
                break
            for col in cols:
                if col == 'subject_type':
                    tmp_str += '"%s",' % (SUBJECT_TYPE_ENUM[row[col]])
                elif col == 'is_standard':
                    tmp_str += '"%s",' % (IS_STANDARDS_ENUM[row[col]])
                elif col == 'trade_amount':
                    tmp_str += '"%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '0')
                else:
                    tmp_str += '"%s",' % (str(row[col]).encode('GBK', 'ignore').decode('gbk') if row[col] else '')
            yield tmp_str.strip(',') + "\n"